Changeset - d208416c84c6
[Not reviewed]
Bradley M. Kuhn - 11 years ago 2014-07-03 01:05:10
bkuhn@sfconservancy.org
Rename rhodecode_user to authuser - it is an AuthUser instance
45 files changed with 176 insertions and 176 deletions:
0 comments (0 inline, 0 general)
kallithea/controllers/admin/gists.py
Show inline comments
 
@@ -24,204 +24,204 @@ gist controller for RhodeCode
 
"""
 

	
 
import time
 
import logging
 
import traceback
 
import formencode
 
from formencode import htmlfill
 

	
 
from pylons import request, response, tmpl_context as c, url
 
from pylons.controllers.util import abort, redirect
 
from pylons.i18n.translation import _
 

	
 
from kallithea.model.forms import GistForm
 
from kallithea.model.gist import GistModel
 
from kallithea.model.meta import Session
 
from kallithea.model.db import Gist, User
 
from kallithea.lib import helpers as h
 
from kallithea.lib.base import BaseController, render
 
from kallithea.lib.auth import LoginRequired, NotAnonymous
 
from kallithea.lib.utils import jsonify
 
from kallithea.lib.utils2 import safe_str, safe_int, time_to_datetime
 
from kallithea.lib.helpers import Page
 
from webob.exc import HTTPNotFound, HTTPForbidden
 
from sqlalchemy.sql.expression import or_
 
from kallithea.lib.vcs.exceptions import VCSError, NodeNotChangedError
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class GistsController(BaseController):
 
    """REST Controller styled on the Atom Publishing Protocol"""
 

	
 
    def __load_defaults(self, extra_values=None):
 
        c.lifetime_values = [
 
            (str(-1), _('forever')),
 
            (str(5), _('5 minutes')),
 
            (str(60), _('1 hour')),
 
            (str(60 * 24), _('1 day')),
 
            (str(60 * 24 * 30), _('1 month')),
 
        ]
 
        if extra_values:
 
            c.lifetime_values.append(extra_values)
 
        c.lifetime_options = [(c.lifetime_values, _("Lifetime"))]
 

	
 
    @LoginRequired()
 
    def index(self):
 
        """GET /admin/gists: All items in the collection"""
 
        # url('gists')
 
        not_default_user = c.rhodecode_user.username != User.DEFAULT_USER
 
        not_default_user = c.authuser.username != User.DEFAULT_USER
 
        c.show_private = request.GET.get('private') and not_default_user
 
        c.show_public = request.GET.get('public') and not_default_user
 

	
 
        gists = Gist().query()\
 
            .filter(or_(Gist.gist_expires == -1, Gist.gist_expires >= time.time()))\
 
            .order_by(Gist.created_on.desc())
 

	
 
        # MY private
 
        if c.show_private and not c.show_public:
 
            gists = gists.filter(Gist.gist_type == Gist.GIST_PRIVATE)\
 
                             .filter(Gist.gist_owner == c.rhodecode_user.user_id)
 
                             .filter(Gist.gist_owner == c.authuser.user_id)
 
        # MY public
 
        elif c.show_public and not c.show_private:
 
            gists = gists.filter(Gist.gist_type == Gist.GIST_PUBLIC)\
 
                             .filter(Gist.gist_owner == c.rhodecode_user.user_id)
 
                             .filter(Gist.gist_owner == c.authuser.user_id)
 

	
 
        # MY public+private
 
        elif c.show_private and c.show_public:
 
            gists = gists.filter(or_(Gist.gist_type == Gist.GIST_PUBLIC,
 
                                     Gist.gist_type == Gist.GIST_PRIVATE))\
 
                             .filter(Gist.gist_owner == c.rhodecode_user.user_id)
 
                             .filter(Gist.gist_owner == c.authuser.user_id)
 

	
 
        # default show ALL public gists
 
        if not c.show_public and not c.show_private:
 
            gists = gists.filter(Gist.gist_type == Gist.GIST_PUBLIC)
 

	
 
        c.gists = gists
 
        p = safe_int(request.GET.get('page', 1), 1)
 
        c.gists_pager = Page(c.gists, page=p, items_per_page=10)
 
        return render('admin/gists/index.html')
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    def create(self):
 
        """POST /admin/gists: Create a new item"""
 
        # url('gists')
 
        self.__load_defaults()
 
        gist_form = GistForm([x[0] for x in c.lifetime_values])()
 
        try:
 
            form_result = gist_form.to_python(dict(request.POST))
 
            #TODO: multiple files support, from the form
 
            filename = form_result['filename'] or Gist.DEFAULT_FILENAME
 
            nodes = {
 
                filename: {
 
                    'content': form_result['content'],
 
                    'lexer': form_result['mimetype']  # None is autodetect
 
                }
 
            }
 
            _public = form_result['public']
 
            gist_type = Gist.GIST_PUBLIC if _public else Gist.GIST_PRIVATE
 
            gist = GistModel().create(
 
                description=form_result['description'],
 
                owner=c.rhodecode_user.user_id,
 
                owner=c.authuser.user_id,
 
                gist_mapping=nodes,
 
                gist_type=gist_type,
 
                lifetime=form_result['lifetime']
 
            )
 
            Session().commit()
 
            new_gist_id = gist.gist_access_id
 
        except formencode.Invalid, errors:
 
            defaults = errors.value
 

	
 
            return formencode.htmlfill.render(
 
                render('admin/gists/new.html'),
 
                defaults=defaults,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8"
 
            )
 

	
 
        except Exception, e:
 
            log.error(traceback.format_exc())
 
            h.flash(_('Error occurred during gist creation'), category='error')
 
            return redirect(url('new_gist'))
 
        return redirect(url('gist', gist_id=new_gist_id))
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    def new(self, format='html'):
 
        """GET /admin/gists/new: Form to create a new item"""
 
        # url('new_gist')
 
        self.__load_defaults()
 
        return render('admin/gists/new.html')
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    def update(self, gist_id):
 
        """PUT /admin/gists/gist_id: 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('gist', gist_id=ID),
 
        #           method='put')
 
        # url('gist', gist_id=ID)
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    def delete(self, gist_id):
 
        """DELETE /admin/gists/gist_id: 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('gist', gist_id=ID),
 
        #           method='delete')
 
        # url('gist', gist_id=ID)
 
        gist = GistModel().get_gist(gist_id)
 
        owner = gist.gist_owner == c.rhodecode_user.user_id
 
        owner = gist.gist_owner == c.authuser.user_id
 
        if h.HasPermissionAny('hg.admin')() or owner:
 
            GistModel().delete(gist)
 
            Session().commit()
 
            h.flash(_('Deleted gist %s') % gist.gist_access_id, category='success')
 
        else:
 
            raise HTTPForbidden()
 

	
 
        return redirect(url('gists'))
 

	
 
    @LoginRequired()
 
    def show(self, gist_id, revision='tip', format='html', f_path=None):
 
        """GET /admin/gists/gist_id: Show a specific item"""
 
        # url('gist', gist_id=ID)
 
        c.gist = Gist.get_or_404(gist_id)
 

	
 
        #check if this gist is not expired
 
        if c.gist.gist_expires != -1:
 
            if time.time() > c.gist.gist_expires:
 
                log.error('Gist expired at %s' %
 
                          (time_to_datetime(c.gist.gist_expires)))
 
                raise HTTPNotFound()
 
        try:
 
            c.file_changeset, c.files = GistModel().get_gist_files(gist_id,
 
                                                            revision=revision)
 
        except VCSError:
 
            log.error(traceback.format_exc())
 
            raise HTTPNotFound()
 
        if format == 'raw':
 
            content = '\n\n'.join([f.content for f in c.files if (f_path is None or f.path == f_path)])
 
            response.content_type = 'text/plain'
 
            return content
 
        return render('admin/gists/show.html')
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    def edit(self, gist_id, format='html'):
 
        """GET /admin/gists/gist_id/edit: Form to edit an existing item"""
 
        # url('edit_gist', gist_id=ID)
 
        c.gist = Gist.get_or_404(gist_id)
 

	
 
        #check if this gist is not expired
 
        if c.gist.gist_expires != -1:
 
            if time.time() > c.gist.gist_expires:
 
                log.error('Gist expired at %s' %
 
                          (time_to_datetime(c.gist.gist_expires)))
 
                raise HTTPNotFound()
 
        try:
 
            c.file_changeset, c.files = GistModel().get_gist_files(gist_id)
kallithea/controllers/admin/my_account.py
Show inline comments
 
@@ -18,273 +18,273 @@ kallithea.controllers.admin.my_account
 
my account controller for rhodecode admin
 

	
 
:created_on: August 20, 2013
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH.
 
:license: GPLv3, see LICENSE for more details.
 
"""
 

	
 
import time
 
import logging
 
import traceback
 
import formencode
 

	
 
from sqlalchemy import func, or_
 
from formencode import htmlfill
 
from pylons import request, tmpl_context as c, url
 
from pylons.controllers.util import redirect
 
from pylons.i18n.translation import _
 

	
 
from kallithea.lib import helpers as h
 
from kallithea.lib.auth import LoginRequired, NotAnonymous, AuthUser
 
from kallithea.lib.base import BaseController, render
 
from kallithea.lib.utils2 import generate_api_key, safe_int
 
from kallithea.lib.compat import json
 
from kallithea.model.db import Repository, PullRequest, PullRequestReviewers, \
 
    UserEmailMap, UserApiKeys, User, UserFollowing
 
from kallithea.model.forms import UserForm, PasswordChangeForm
 
from kallithea.model.user import UserModel
 
from kallithea.model.repo import RepoModel
 
from kallithea.model.api_key import ApiKeyModel
 
from kallithea.model.meta import Session
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class MyAccountController(BaseController):
 
    """REST Controller styled on the Atom Publishing Protocol"""
 
    # To properly map this controller, ensure your config/routing.py
 
    # file has a resource setup:
 
    #     map.resource('setting', 'settings', controller='admin/settings',
 
    #         path_prefix='/admin', name_prefix='admin_')
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    def __before__(self):
 
        super(MyAccountController, self).__before__()
 

	
 
    def __load_data(self):
 
        c.user = User.get(self.rhodecode_user.user_id)
 
        c.user = User.get(self.authuser.user_id)
 
        if c.user.username == User.DEFAULT_USER:
 
            h.flash(_("You can't edit this user since it's"
 
                      " crucial for entire application"), category='warning')
 
            return redirect(url('users'))
 

	
 
    def _load_my_repos_data(self, watched=False):
 
        if watched:
 
            admin = False
 
            repos_list = [x.follows_repository for x in
 
                          Session().query(UserFollowing).filter(
 
                              UserFollowing.user_id ==
 
                              self.rhodecode_user.user_id).all()]
 
                              self.authuser.user_id).all()]
 
        else:
 
            admin = True
 
            repos_list = Session().query(Repository)\
 
                         .filter(Repository.user_id ==
 
                                 self.rhodecode_user.user_id)\
 
                                 self.authuser.user_id)\
 
                         .order_by(func.lower(Repository.repo_name)).all()
 

	
 
        repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list,
 
                                                   admin=admin)
 
        #json used to render the grid
 
        return json.dumps(repos_data)
 

	
 
    def my_account(self):
 
        """
 
        GET /_admin/my_account Displays info about my account
 
        """
 
        # url('my_account')
 
        c.active = 'profile'
 
        self.__load_data()
 
        c.perm_user = AuthUser(user_id=self.rhodecode_user.user_id,
 
        c.perm_user = AuthUser(user_id=self.authuser.user_id,
 
                               ip_addr=self.ip_addr)
 
        c.extern_type = c.user.extern_type
 
        c.extern_name = c.user.extern_name
 

	
 
        defaults = c.user.get_dict()
 
        update = False
 
        if request.POST:
 
            _form = UserForm(edit=True,
 
                             old_data={'user_id': self.rhodecode_user.user_id,
 
                                       'email': self.rhodecode_user.email})()
 
                             old_data={'user_id': self.authuser.user_id,
 
                                       'email': self.authuser.email})()
 
            form_result = {}
 
            try:
 
                post_data = dict(request.POST)
 
                post_data['new_password'] = ''
 
                post_data['password_confirmation'] = ''
 
                form_result = _form.to_python(post_data)
 
                # skip updating those attrs for my account
 
                skip_attrs = ['admin', 'active', 'extern_type', 'extern_name',
 
                              'new_password', 'password_confirmation']
 
                #TODO: plugin should define if username can be updated
 
                if c.extern_type != "rhodecode":
 
                    # forbid updating username for external accounts
 
                    skip_attrs.append('username')
 

	
 
                UserModel().update(self.rhodecode_user.user_id, form_result,
 
                UserModel().update(self.authuser.user_id, form_result,
 
                                   skip_attrs=skip_attrs)
 
                h.flash(_('Your account was updated successfully'),
 
                        category='success')
 
                Session().commit()
 
                update = True
 

	
 
            except formencode.Invalid, errors:
 
                return htmlfill.render(
 
                    render('admin/my_account/my_account.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 occurred during update of user %s') \
 
                        % form_result.get('username'), category='error')
 
        if update:
 
            return redirect('my_account')
 
        return htmlfill.render(
 
            render('admin/my_account/my_account.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )
 

	
 
    def my_account_password(self):
 
        c.active = 'password'
 
        self.__load_data()
 
        if request.POST:
 
            _form = PasswordChangeForm(self.rhodecode_user.username)()
 
            _form = PasswordChangeForm(self.authuser.username)()
 
            try:
 
                form_result = _form.to_python(request.POST)
 
                UserModel().update(self.rhodecode_user.user_id, form_result)
 
                UserModel().update(self.authuser.user_id, form_result)
 
                Session().commit()
 
                h.flash(_("Successfully updated password"), category='success')
 
            except formencode.Invalid as errors:
 
                return htmlfill.render(
 
                    render('admin/my_account/my_account.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 occurred during update of user password'),
 
                        category='error')
 
        return render('admin/my_account/my_account.html')
 

	
 
    def my_account_repos(self):
 
        c.active = 'repos'
 
        self.__load_data()
 

	
 
        #json used to render the grid
 
        c.data = self._load_my_repos_data()
 
        return render('admin/my_account/my_account.html')
 

	
 
    def my_account_watched(self):
 
        c.active = 'watched'
 
        self.__load_data()
 

	
 
        #json used to render the grid
 
        c.data = self._load_my_repos_data(watched=True)
 
        return render('admin/my_account/my_account.html')
 

	
 
    def my_account_perms(self):
 
        c.active = 'perms'
 
        self.__load_data()
 
        c.perm_user = AuthUser(user_id=self.rhodecode_user.user_id,
 
        c.perm_user = AuthUser(user_id=self.authuser.user_id,
 
                               ip_addr=self.ip_addr)
 

	
 
        return render('admin/my_account/my_account.html')
 

	
 
    def my_account_emails(self):
 
        c.active = 'emails'
 
        self.__load_data()
 

	
 
        c.user_email_map = UserEmailMap.query()\
 
            .filter(UserEmailMap.user == c.user).all()
 
        return render('admin/my_account/my_account.html')
 

	
 
    def my_account_emails_add(self):
 
        email = request.POST.get('new_email')
 

	
 
        try:
 
            UserModel().add_extra_email(self.rhodecode_user.user_id, email)
 
            UserModel().add_extra_email(self.authuser.user_id, email)
 
            Session().commit()
 
            h.flash(_("Added email %s to user") % email, category='success')
 
        except formencode.Invalid, error:
 
            msg = error.error_dict['email']
 
            h.flash(msg, category='error')
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during email saving'),
 
                    category='error')
 
        return redirect(url('my_account_emails'))
 

	
 
    def my_account_emails_delete(self):
 
        email_id = request.POST.get('del_email_id')
 
        user_model = UserModel()
 
        user_model.delete_extra_email(self.rhodecode_user.user_id, email_id)
 
        user_model.delete_extra_email(self.authuser.user_id, email_id)
 
        Session().commit()
 
        h.flash(_("Removed email from user"), category='success')
 
        return redirect(url('my_account_emails'))
 

	
 
    def my_account_pullrequests(self):
 
        c.active = 'pullrequests'
 
        self.__load_data()
 
        c.show_closed = request.GET.get('pr_show_closed')
 

	
 
        def _filter(pr):
 
            s = sorted(pr, key=lambda o: o.created_on, reverse=True)
 
            if not c.show_closed:
 
                s = filter(lambda p: p.status != PullRequest.STATUS_CLOSED, s)
 
            return s
 

	
 
        c.my_pull_requests = _filter(PullRequest.query()\
 
                                .filter(PullRequest.user_id ==
 
                                        self.rhodecode_user.user_id)\
 
                                        self.authuser.user_id)\
 
                                .all())
 
        my_prs = [x.pull_request for x in PullRequestReviewers.query()
 
                    .filter(PullRequestReviewers.user_id ==
 
                        self.rhodecode_user.user_id).all()]
 
                        self.authuser.user_id).all()]
 
        c.participate_in_pull_requests = _filter(my_prs)
 
        return render('admin/my_account/my_account.html')
 

	
 
    def my_account_api_keys(self):
 
        c.active = 'api_keys'
 
        self.__load_data()
 
        show_expired = True
 
        c.lifetime_values = [
 
            (str(-1), _('forever')),
 
            (str(5), _('5 minutes')),
 
            (str(60), _('1 hour')),
 
            (str(60 * 24), _('1 day')),
 
            (str(60 * 24 * 30), _('1 month')),
 
        ]
 
        c.lifetime_options = [(c.lifetime_values, _("Lifetime"))]
 
        c.user_api_keys = ApiKeyModel().get_api_keys(self.rhodecode_user.user_id,
 
        c.user_api_keys = ApiKeyModel().get_api_keys(self.authuser.user_id,
 
                                                     show_expired=show_expired)
 
        return render('admin/my_account/my_account.html')
 

	
 
    def my_account_api_keys_add(self):
 
        lifetime = safe_int(request.POST.get('lifetime'), -1)
 
        description = request.POST.get('description')
 
        new_api_key = ApiKeyModel().create(self.rhodecode_user.user_id,
 
        new_api_key = ApiKeyModel().create(self.authuser.user_id,
 
                                           description, lifetime)
 
        Session().commit()
 
        h.flash(_("Api key successfully created"), category='success')
 
        return redirect(url('my_account_api_keys'))
 

	
 
    def my_account_api_keys_delete(self):
 
        api_key = request.POST.get('del_api_key')
 
        user_id = self.rhodecode_user.user_id
 
        user_id = self.authuser.user_id
 
        if request.POST.get('del_api_key_builtin'):
 
            user = User.get(user_id)
 
            if user:
 
                user.api_key = generate_api_key(user.username)
 
                Session().add(user)
 
                Session().commit()
 
                h.flash(_("Api key successfully reset"), category='success')
 
        elif api_key:
 
            ApiKeyModel().delete(api_key, self.rhodecode_user.user_id)
 
            ApiKeyModel().delete(api_key, self.authuser.user_id)
 
            Session().commit()
 
            h.flash(_("Api key successfully deleted"), category='success')
 

	
 
        return redirect(url('my_account_api_keys'))
kallithea/controllers/admin/notifications.py
Show inline comments
 
@@ -14,160 +14,160 @@
 
"""
 
kallithea.controllers.admin.notifications
 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
notifications controller for RhodeCode
 

	
 
:created_on: Nov 23, 2010
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH.
 
:license: GPLv3, see LICENSE for more details.
 
"""
 

	
 
import logging
 
import traceback
 

	
 
from pylons import request
 
from pylons import tmpl_context as c, url
 
from pylons.controllers.util import redirect, abort
 
from webob.exc import HTTPBadRequest
 

	
 
from kallithea.model.db import Notification
 
from kallithea.model.notification import NotificationModel
 
from kallithea.model.meta import Session
 
from kallithea.lib.auth import LoginRequired, NotAnonymous
 
from kallithea.lib.base import BaseController, render
 
from kallithea.lib import helpers as h
 
from kallithea.lib.helpers import Page
 
from kallithea.lib.utils2 import safe_int
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class NotificationsController(BaseController):
 
    """REST Controller styled on the Atom Publishing Protocol"""
 
    # To properly map this controller, ensure your config/routing.py
 
    # file has a resource setup:
 
    #     map.resource('notification', 'notifications', controller='_admin/notifications',
 
    #         path_prefix='/_admin', name_prefix='_admin_')
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    def __before__(self):
 
        super(NotificationsController, self).__before__()
 

	
 
    def index(self, format='html'):
 
        """GET /_admin/notifications: All items in the collection"""
 
        # url('notifications')
 
        c.user = self.rhodecode_user
 
        notif = NotificationModel().get_for_user(self.rhodecode_user.user_id,
 
        c.user = self.authuser
 
        notif = NotificationModel().get_for_user(self.authuser.user_id,
 
                                            filter_=request.GET.getall('type'))
 

	
 
        p = safe_int(request.GET.get('page', 1), 1)
 
        c.notifications = Page(notif, page=p, items_per_page=10)
 
        c.pull_request_type = Notification.TYPE_PULL_REQUEST
 
        c.comment_type = [Notification.TYPE_CHANGESET_COMMENT,
 
                          Notification.TYPE_PULL_REQUEST_COMMENT]
 

	
 
        _current_filter = request.GET.getall('type')
 
        c.current_filter = 'all'
 
        if _current_filter == [c.pull_request_type]:
 
            c.current_filter = 'pull_request'
 
        elif _current_filter == c.comment_type:
 
            c.current_filter = 'comment'
 

	
 
        return render('admin/notifications/notifications.html')
 

	
 
    def mark_all_read(self):
 
        if request.environ.get('HTTP_X_PARTIAL_XHR'):
 
            nm = NotificationModel()
 
            # mark all read
 
            nm.mark_all_read_for_user(self.rhodecode_user.user_id,
 
            nm.mark_all_read_for_user(self.authuser.user_id,
 
                                      filter_=request.GET.getall('type'))
 
            Session().commit()
 
            c.user = self.rhodecode_user
 
            notif = nm.get_for_user(self.rhodecode_user.user_id,
 
            c.user = self.authuser
 
            notif = nm.get_for_user(self.authuser.user_id,
 
                                    filter_=request.GET.getall('type'))
 
            c.notifications = Page(notif, page=1, items_per_page=10)
 
            return render('admin/notifications/notifications_data.html')
 

	
 
    def create(self):
 
        """POST /_admin/notifications: Create a new item"""
 
        # url('notifications')
 

	
 
    def new(self, format='html'):
 
        """GET /_admin/notifications/new: Form to create a new item"""
 
        # url('new_notification')
 

	
 
    def update(self, notification_id):
 
        """PUT /_admin/notifications/id: 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('notification', notification_id=ID),
 
        #           method='put')
 
        # url('notification', notification_id=ID)
 
        try:
 
            no = Notification.get(notification_id)
 
            owner = all(un.user.user_id == c.rhodecode_user.user_id
 
            owner = all(un.user.user_id == c.authuser.user_id
 
                        for un in no.notifications_to_users)
 
            if h.HasPermissionAny('hg.admin')() or owner:
 
                # deletes only notification2user
 
                NotificationModel().mark_read(c.rhodecode_user.user_id, no)
 
                NotificationModel().mark_read(c.authuser.user_id, no)
 
                Session().commit()
 
                return 'ok'
 
        except Exception:
 
            Session().rollback()
 
            log.error(traceback.format_exc())
 
        raise HTTPBadRequest()
 

	
 
    def delete(self, notification_id):
 
        """DELETE /_admin/notifications/id: 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('notification', notification_id=ID),
 
        #           method='delete')
 
        # url('notification', notification_id=ID)
 
        try:
 
            no = Notification.get(notification_id)
 
            owner = any(un.user.user_id == c.rhodecode_user.user_id
 
            owner = any(un.user.user_id == c.authuser.user_id
 
                        for un in no.notifications_to_users)
 
            if h.HasPermissionAny('hg.admin')() or owner:
 
                # deletes only notification2user
 
                NotificationModel().delete(c.rhodecode_user.user_id, no)
 
                NotificationModel().delete(c.authuser.user_id, no)
 
                Session().commit()
 
                return 'ok'
 
        except Exception:
 
            Session().rollback()
 
            log.error(traceback.format_exc())
 
        raise HTTPBadRequest()
 

	
 
    def show(self, notification_id, format='html'):
 
        """GET /_admin/notifications/id: Show a specific item"""
 
        # url('notification', notification_id=ID)
 
        c.user = self.rhodecode_user
 
        c.user = self.authuser
 
        no = Notification.get(notification_id)
 

	
 
        owner = any(un.user.user_id == c.rhodecode_user.user_id
 
        owner = any(un.user.user_id == c.authuser.user_id
 
                    for un in no.notifications_to_users)
 
        repo_admin = h.HasRepoPermissionAny('repository.admin')
 
        if no and (h.HasPermissionAny('hg.admin')() or repo_admin or owner):
 
            unotification = NotificationModel()\
 
                            .get_user_notification(c.user.user_id, no)
 

	
 
            # if this association to user is not valid, we don't want to show
 
            # this message
 
            if unotification:
 
                if not unotification.read:
 
                    unotification.mark_as_read()
 
                    Session().commit()
 
                c.notification = no
 

	
 
                return render('admin/notifications/show_notification.html')
 

	
 
        return abort(403)
 

	
 
    def edit(self, notification_id, format='html'):
 
        """GET /_admin/notifications/id/edit: Form to edit an existing item"""
 
        # url('edit_notification', notification_id=ID)
kallithea/controllers/admin/repo_groups.py
Show inline comments
 
@@ -61,168 +61,168 @@ class RepoGroupsController(BaseControlle
 
    """REST Controller styled on the Atom Publishing Protocol"""
 

	
 
    @LoginRequired()
 
    def __before__(self):
 
        super(RepoGroupsController, self).__before__()
 

	
 
    def __load_defaults(self, allow_empty_group=False, exclude_group_ids=[]):
 
        if HasPermissionAll('hg.admin')('group edit'):
 
            #we're global admin, we're ok and we can create TOP level groups
 
            allow_empty_group = True
 

	
 
        #override the choices for this form, we need to filter choices
 
        #and display only those we have ADMIN right
 
        groups_with_admin_rights = RepoGroupList(RepoGroup.query().all(),
 
                                                 perm_set=['group.admin'])
 
        c.repo_groups = RepoGroup.groups_choices(groups=groups_with_admin_rights,
 
                                                 show_empty_group=allow_empty_group)
 
        # exclude filtered ids
 
        c.repo_groups = filter(lambda x: x[0] not in exclude_group_ids,
 
                               c.repo_groups)
 
        c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
 
        repo_model = RepoModel()
 
        c.users_array = repo_model.get_users_js()
 
        c.user_groups_array = repo_model.get_user_groups_js()
 

	
 
    def __load_data(self, group_id):
 
        """
 
        Load defaults settings for edit, and update
 

	
 
        :param group_id:
 
        """
 
        repo_group = RepoGroup.get_or_404(group_id)
 
        data = repo_group.get_dict()
 
        data['group_name'] = repo_group.name
 

	
 
        # fill repository group users
 
        for p in repo_group.repo_group_to_perm:
 
            data.update({'u_perm_%s' % p.user.username:
 
                             p.permission.permission_name})
 

	
 
        # fill repository group groups
 
        for p in repo_group.users_group_to_perm:
 
            data.update({'g_perm_%s' % p.users_group.users_group_name:
 
                             p.permission.permission_name})
 

	
 
        return data
 

	
 
    def _revoke_perms_on_yourself(self, form_result):
 
        _up = filter(lambda u: c.rhodecode_user.username == u[0],
 
        _up = filter(lambda u: c.authuser.username == u[0],
 
                     form_result['perms_updates'])
 
        _new = filter(lambda u: c.rhodecode_user.username == u[0],
 
        _new = filter(lambda u: c.authuser.username == u[0],
 
                      form_result['perms_new'])
 
        if _new and _new[0][1] != 'group.admin' or _up and _up[0][1] != 'group.admin':
 
            return True
 
        return False
 

	
 
    def index(self, format='html'):
 
        """GET /repo_groups: All items in the collection"""
 
        # url('repos_groups')
 
        _list = RepoGroup.query()\
 
                    .order_by(func.lower(RepoGroup.group_name))\
 
                    .all()
 
        group_iter = RepoGroupList(_list, perm_set=['group.admin'])
 
        repo_groups_data = []
 
        total_records = len(group_iter)
 
        _tmpl_lookup = kallithea.CONFIG['pylons.app_globals'].mako_lookup
 
        template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
 

	
 
        repo_group_name = lambda repo_group_name, children_groups: (
 
            template.get_def("repo_group_name")
 
            .render(repo_group_name, children_groups, _=_, h=h, c=c)
 
        )
 
        repo_group_actions = lambda repo_group_id, repo_group_name, gr_count: (
 
            template.get_def("repo_group_actions")
 
            .render(repo_group_id, repo_group_name, gr_count, _=_, h=h, c=c,
 
                    ungettext=ungettext)
 
        )
 

	
 
        for repo_gr in group_iter:
 
            children_groups = map(h.safe_unicode,
 
                itertools.chain((g.name for g in repo_gr.parents),
 
                                (x.name for x in [repo_gr])))
 
            repo_count = repo_gr.repositories.count()
 
            repo_groups_data.append({
 
                "raw_name": repo_gr.group_name,
 
                "group_name": repo_group_name(repo_gr.group_name, children_groups),
 
                "desc": repo_gr.group_description,
 
                "repos": repo_count,
 
                "owner": h.person(repo_gr.user.username),
 
                "action": repo_group_actions(repo_gr.group_id, repo_gr.group_name,
 
                                             repo_count)
 
            })
 

	
 
        c.data = json.dumps({
 
            "totalRecords": total_records,
 
            "startIndex": 0,
 
            "sort": None,
 
            "dir": "asc",
 
            "records": repo_groups_data
 
        })
 

	
 
        return render('admin/repo_groups/repo_groups.html')
 

	
 
    def create(self):
 
        """POST /repo_groups: Create a new item"""
 
        # url('repos_groups')
 

	
 
        self.__load_defaults()
 

	
 
        # permissions for can create group based on parent_id are checked
 
        # here in the Form
 
        repo_group_form = RepoGroupForm(available_groups=
 
                                map(lambda k: unicode(k[0]), c.repo_groups))()
 
        try:
 
            form_result = repo_group_form.to_python(dict(request.POST))
 
            RepoGroupModel().create(
 
                group_name=form_result['group_name'],
 
                group_description=form_result['group_description'],
 
                parent=form_result['group_parent_id'],
 
                owner=self.rhodecode_user.user_id,
 
                owner=self.authuser.user_id,
 
                copy_permissions=form_result['group_copy_permissions']
 
            )
 
            Session().commit()
 
            h.flash(_('Created repository group %s') \
 
                    % form_result['group_name'], category='success')
 
            #TODO: in futureaction_logger(, '', '', '', self.sa)
 
        except formencode.Invalid, errors:
 
            return htmlfill.render(
 
                render('admin/repo_groups/repo_group_add.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 occurred during creation of repository group %s') \
 
                    % request.POST.get('group_name'), category='error')
 
        parent_group_id = form_result['group_parent_id']
 
        #TODO: maybe we should get back to the main view, not the admin one
 
        return redirect(url('repos_groups', parent_group=parent_group_id))
 

	
 
    def new(self):
 
        """GET /repo_groups/new: Form to create a new item"""
 
        # url('new_repos_group')
 
        if HasPermissionAll('hg.admin')('group create'):
 
            #we're global admin, we're ok and we can create TOP level groups
 
            pass
 
        else:
 
            # we pass in parent group into creation form, thus we know
 
            # what would be the group, we can check perms here !
 
            group_id = safe_int(request.GET.get('parent_group'))
 
            group = RepoGroup.get(group_id) if group_id else None
 
            group_name = group.group_name if group else None
 
            if HasRepoGroupPermissionAll('group.admin')(group_name, 'group create'):
 
                pass
 
            else:
 
                return abort(403)
 

	
 
        self.__load_defaults()
 
        return render('admin/repo_groups/repo_group_add.html')
 

	
 
    @HasRepoGroupPermissionAnyDecorator('group.admin')
 
    def update(self, group_name):
 
        """PUT /repo_groups/group_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('repos_group', group_name=GROUP_NAME),
 
@@ -367,105 +367,105 @@ class RepoGroupsController(BaseControlle
 

	
 
        self.__load_defaults(allow_empty_group=allow_empty_group,
 
                             exclude_group_ids=[c.repo_group.group_id])
 
        defaults = self.__load_data(c.repo_group.group_id)
 

	
 
        return htmlfill.render(
 
            render('admin/repo_groups/repo_group_edit.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )
 

	
 
    @HasRepoGroupPermissionAnyDecorator('group.admin')
 
    def edit_repo_group_advanced(self, group_name):
 
        """GET /repo_groups/group_name/edit: Form to edit an existing item"""
 
        # url('edit_repo_group', group_name=GROUP_NAME)
 
        c.active = 'advanced'
 
        c.repo_group = RepoGroupModel()._get_repo_group(group_name)
 

	
 
        return render('admin/repo_groups/repo_group_edit.html')
 

	
 
    @HasRepoGroupPermissionAnyDecorator('group.admin')
 
    def edit_repo_group_perms(self, group_name):
 
        """GET /repo_groups/group_name/edit: Form to edit an existing item"""
 
        # url('edit_repo_group', group_name=GROUP_NAME)
 
        c.active = 'perms'
 
        c.repo_group = RepoGroupModel()._get_repo_group(group_name)
 
        self.__load_defaults()
 
        defaults = self.__load_data(c.repo_group.group_id)
 

	
 
        return htmlfill.render(
 
            render('admin/repo_groups/repo_group_edit.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )
 

	
 
    @HasRepoGroupPermissionAnyDecorator('group.admin')
 
    def update_perms(self, group_name):
 
        """
 
        Update permissions for given repository group
 

	
 
        :param group_name:
 
        """
 

	
 
        c.repo_group = RepoGroupModel()._get_repo_group(group_name)
 
        valid_recursive_choices = ['none', 'repos', 'groups', 'all']
 
        form_result = RepoGroupPermsForm(valid_recursive_choices)().to_python(request.POST)
 
        if not c.rhodecode_user.is_admin:
 
        if not c.authuser.is_admin:
 
            if self._revoke_perms_on_yourself(form_result):
 
                msg = _('Cannot revoke permission for yourself as admin')
 
                h.flash(msg, category='warning')
 
                return redirect(url('edit_repo_group_perms', group_name=group_name))
 
        recursive = form_result['recursive']
 
        # iterate over all members(if in recursive mode) of this groups and
 
        # set the permissions !
 
        # this can be potentially heavy operation
 
        RepoGroupModel()._update_permissions(c.repo_group,
 
                                             form_result['perms_new'],
 
                                             form_result['perms_updates'],
 
                                             recursive)
 
        #TODO: implement this
 
        #action_logger(self.rhodecode_user, 'admin_changed_repo_permissions',
 
        #action_logger(self.authuser, 'admin_changed_repo_permissions',
 
        #              repo_name, self.ip_addr, self.sa)
 
        Session().commit()
 
        h.flash(_('Repository Group permissions updated'), category='success')
 
        return redirect(url('edit_repo_group_perms', group_name=group_name))
 

	
 
    @HasRepoGroupPermissionAnyDecorator('group.admin')
 
    def delete_perms(self, group_name):
 
        """
 
        DELETE an existing repository group permission user
 

	
 
        :param group_name:
 
        """
 
        try:
 
            obj_type = request.POST.get('obj_type')
 
            obj_id = None
 
            if obj_type == 'user':
 
                obj_id = safe_int(request.POST.get('user_id'))
 
            elif obj_type == 'user_group':
 
                obj_id = safe_int(request.POST.get('user_group_id'))
 

	
 
            if not c.rhodecode_user.is_admin:
 
                if obj_type == 'user' and c.rhodecode_user.user_id == obj_id:
 
            if not c.authuser.is_admin:
 
                if obj_type == 'user' and c.authuser.user_id == obj_id:
 
                    msg = _('Cannot revoke permission for yourself as admin')
 
                    h.flash(msg, category='warning')
 
                    raise Exception('revoke admin permission on self')
 
            recursive = request.POST.get('recursive', 'none')
 
            if obj_type == 'user':
 
                RepoGroupModel().delete_permission(repo_group=group_name,
 
                                                   obj=obj_id, obj_type='user',
 
                                                   recursive=recursive)
 
            elif obj_type == 'user_group':
 
                RepoGroupModel().delete_permission(repo_group=group_name,
 
                                                   obj=obj_id,
 
                                                   obj_type='user_group',
 
                                                   recursive=recursive)
 

	
 
            Session().commit()
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during revoking of permission'),
 
                    category='error')
 
            raise HTTPInternalServerError()
kallithea/controllers/admin/repos.py
Show inline comments
 
@@ -98,97 +98,97 @@ class ReposController(BaseRepoController
 
        """
 
        Load defaults settings for edit, and update
 

	
 
        :param repo_name:
 
        """
 
        c.repo_info = self._load_repo(repo_name)
 
        self.__load_defaults(c.repo_info)
 

	
 
        ##override defaults for exact repo info here git/hg etc
 
        choices, c.landing_revs = ScmModel().get_repo_landing_revs(c.repo_info)
 
        c.landing_revs_choices = choices
 
        defaults = RepoModel()._get_defaults(repo_name)
 

	
 
        return defaults
 

	
 
    def index(self, format='html'):
 
        """GET /repos: All items in the collection"""
 
        # url('repos')
 
        _list = Repository.query()\
 
                        .order_by(func.lower(Repository.repo_name))\
 
                        .all()
 

	
 
        c.repos_list = RepoList(_list, perm_set=['repository.admin'])
 
        repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list,
 
                                                   admin=True,
 
                                                   super_user_actions=True)
 
        #json used to render the grid
 
        c.data = json.dumps(repos_data)
 

	
 
        return render('admin/repos/repos.html')
 

	
 
    @NotAnonymous()
 
    def create(self):
 
        """
 
        POST /repos: Create a new item"""
 
        # url('repos')
 

	
 
        self.__load_defaults()
 
        form_result = {}
 
        task_id = None
 
        try:
 
            # CanWriteToGroup validators checks permissions of this POST
 
            form_result = RepoForm(repo_groups=c.repo_groups_choices,
 
                                   landing_revs=c.landing_revs_choices)()\
 
                            .to_python(dict(request.POST))
 

	
 
            # create is done sometimes async on celery, db transaction
 
            # management is handled there.
 
            task = RepoModel().create(form_result, self.rhodecode_user.user_id)
 
            task = RepoModel().create(form_result, self.authuser.user_id)
 
            from celery.result import BaseAsyncResult
 
            if isinstance(task, BaseAsyncResult):
 
                task_id = task.task_id
 
        except formencode.Invalid, errors:
 
            return htmlfill.render(
 
                render('admin/repos/repo_add.html'),
 
                defaults=errors.value,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8")
 

	
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            msg = (_('Error creating repository %s')
 
                   % form_result.get('repo_name'))
 
            h.flash(msg, category='error')
 
            return redirect(url('home'))
 

	
 
        return redirect(h.url('repo_creating_home',
 
                              repo_name=form_result['repo_name_full'],
 
                              task_id=task_id))
 

	
 
    @NotAnonymous()
 
    def create_repository(self):
 
        """GET /_admin/create_repository: Form to create a new item"""
 
        new_repo = request.GET.get('repo', '')
 
        parent_group = request.GET.get('parent_group')
 
        if not HasPermissionAny('hg.admin', 'hg.create.repository')():
 
            #you're not super admin nor have global create permissions,
 
            #but maybe you have at least write permission to a parent group ?
 
            _gr = RepoGroup.get(parent_group)
 
            gr_name = _gr.group_name if _gr else None
 
            # create repositories with write permission on group is set to true
 
            create_on_write = HasPermissionAny('hg.create.write_on_repogroup.true')()
 
            group_admin = HasRepoGroupPermissionAny('group.admin')(group_name=gr_name)
 
            group_write = HasRepoGroupPermissionAny('group.write')(group_name=gr_name)
 
            if not (group_admin or (group_write and create_on_write)):
 
                raise HTTPForbidden
 

	
 
        acl_groups = RepoGroupList(RepoGroup.query().all(),
 
                               perm_set=['group.write', 'group.admin'])
 
        c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
 
        c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
 
        choices, c.landing_revs = ScmModel().get_repo_landing_revs()
 

	
 
        c.new_repo = repo_name_slug(new_repo)
 

	
 
        ## apply the defaults from defaults page
 
@@ -242,226 +242,226 @@ class ReposController(BaseRepoController
 
                if fork:
 
                    fork_name = fork.repo_name
 
                    h.flash(h.literal(_('Forked repository %s as %s')
 
                            % (fork_name, repo_url)), category='success')
 
                else:
 
                    h.flash(h.literal(_('Created repository %s') % repo_url),
 
                            category='success')
 
            return {'result': True}
 
        return {'result': False}
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    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', repo_name=ID),
 
        #           method='put')
 
        # url('repo', repo_name=ID)
 
        c.repo_info = self._load_repo(repo_name)
 
        c.active = 'settings'
 
        c.repo_fields = RepositoryField.query()\
 
            .filter(RepositoryField.repository == c.repo_info).all()
 
        self.__load_defaults(c.repo_info)
 

	
 
        repo_model = RepoModel()
 
        changed_name = repo_name
 
        #override the choices with extracted revisions !
 
        choices, c.landing_revs = ScmModel().get_repo_landing_revs(repo_name)
 
        c.landing_revs_choices = choices
 
        repo = Repository.get_by_repo_name(repo_name)
 
        old_data = {
 
            'repo_name': repo_name,
 
            'repo_group': repo.group.get_dict() if repo.group else {},
 
            'repo_type': repo.repo_type,
 
        }
 
        _form = RepoForm(edit=True, old_data=old_data,
 
                         repo_groups=c.repo_groups_choices,
 
                         landing_revs=c.landing_revs_choices)()
 

	
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            repo = repo_model.update(repo_name, **form_result)
 
            ScmModel().mark_for_invalidation(repo_name)
 
            h.flash(_('Repository %s updated successfully') % repo_name,
 
                    category='success')
 
            changed_name = repo.repo_name
 
            action_logger(self.rhodecode_user, 'admin_updated_repo',
 
            action_logger(self.authuser, 'admin_updated_repo',
 
                              changed_name, self.ip_addr, self.sa)
 
            Session().commit()
 
        except formencode.Invalid, errors:
 
            defaults = self.__load_data(repo_name)
 
            defaults.update(errors.value)
 
            return htmlfill.render(
 
                render('admin/repos/repo_edit.html'),
 
                defaults=defaults,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8")
 

	
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('Error occurred during update of repository %s') \
 
                    % repo_name, category='error')
 
        return redirect(url('edit_repo', repo_name=changed_name))
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    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', repo_name=ID),
 
        #           method='delete')
 
        # url('repo', repo_name=ID)
 

	
 
        repo_model = RepoModel()
 
        repo = repo_model.get_by_repo_name(repo_name)
 
        if not repo:
 
            h.not_mapped_error(repo_name)
 
            return redirect(url('repos'))
 
        try:
 
            _forks = repo.forks.count()
 
            handle_forks = None
 
            if _forks and request.POST.get('forks'):
 
                do = request.POST['forks']
 
                if do == 'detach_forks':
 
                    handle_forks = 'detach'
 
                    h.flash(_('Detached %s forks') % _forks, category='success')
 
                elif do == 'delete_forks':
 
                    handle_forks = 'delete'
 
                    h.flash(_('Deleted %s forks') % _forks, category='success')
 
            repo_model.delete(repo, forks=handle_forks)
 
            action_logger(self.rhodecode_user, 'admin_deleted_repo',
 
            action_logger(self.authuser, 'admin_deleted_repo',
 
                  repo_name, self.ip_addr, self.sa)
 
            ScmModel().mark_for_invalidation(repo_name)
 
            h.flash(_('Deleted repository %s') % repo_name, category='success')
 
            Session().commit()
 
        except AttachedForksError:
 
            h.flash(_('Cannot delete %s it still contains attached forks')
 
                        % repo_name, category='warning')
 

	
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during deletion of %s') % repo_name,
 
                    category='error')
 

	
 
        return redirect(url('repos'))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def show(self, repo_name, format='html'):
 
        """GET /repos/repo_name: Show a specific item"""
 
        # url('repo', repo_name=ID)
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def edit(self, repo_name):
 
        """GET /repo_name/settings: Form to edit an existing item"""
 
        # url('edit_repo', repo_name=ID)
 
        defaults = self.__load_data(repo_name)
 
        if 'clone_uri' in defaults:
 
            del defaults['clone_uri']
 

	
 
        c.repo_fields = RepositoryField.query()\
 
            .filter(RepositoryField.repository == c.repo_info).all()
 
        c.active = 'settings'
 
        return htmlfill.render(
 
            render('admin/repos/repo_edit.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False)
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def edit_permissions(self, repo_name):
 
        """GET /repo_name/settings: Form to edit an existing item"""
 
        # url('edit_repo', repo_name=ID)
 
        c.repo_info = self._load_repo(repo_name)
 
        repo_model = RepoModel()
 
        c.users_array = repo_model.get_users_js()
 
        c.user_groups_array = repo_model.get_user_groups_js()
 
        c.active = 'permissions'
 
        defaults = RepoModel()._get_defaults(repo_name)
 

	
 
        return htmlfill.render(
 
            render('admin/repos/repo_edit.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False)
 

	
 
    def edit_permissions_update(self, repo_name):
 
        form = RepoPermsForm()().to_python(request.POST)
 
        RepoModel()._update_permissions(repo_name, form['perms_new'],
 
                                        form['perms_updates'])
 
        #TODO: implement this
 
        #action_logger(self.rhodecode_user, 'admin_changed_repo_permissions',
 
        #action_logger(self.authuser, 'admin_changed_repo_permissions',
 
        #              repo_name, self.ip_addr, self.sa)
 
        Session().commit()
 
        h.flash(_('Repository permissions updated'), category='success')
 
        return redirect(url('edit_repo_perms', repo_name=repo_name))
 

	
 
    def edit_permissions_revoke(self, repo_name):
 
        try:
 
            obj_type = request.POST.get('obj_type')
 
            obj_id = None
 
            if obj_type == 'user':
 
                obj_id = safe_int(request.POST.get('user_id'))
 
            elif obj_type == 'user_group':
 
                obj_id = safe_int(request.POST.get('user_group_id'))
 

	
 
            if obj_type == 'user':
 
                RepoModel().revoke_user_permission(repo=repo_name, user=obj_id)
 
            elif obj_type == 'user_group':
 
                RepoModel().revoke_user_group_permission(
 
                    repo=repo_name, group_name=obj_id
 
                )
 
            #TODO: implement this
 
            #action_logger(self.rhodecode_user, 'admin_revoked_repo_permissions',
 
            #action_logger(self.authuser, 'admin_revoked_repo_permissions',
 
            #              repo_name, self.ip_addr, self.sa)
 
            Session().commit()
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during revoking of permission'),
 
                    category='error')
 
            raise HTTPInternalServerError()
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def edit_fields(self, repo_name):
 
        """GET /repo_name/settings: Form to edit an existing item"""
 
        # url('edit_repo', repo_name=ID)
 
        c.repo_info = self._load_repo(repo_name)
 
        c.repo_fields = RepositoryField.query()\
 
            .filter(RepositoryField.repository == c.repo_info).all()
 
        c.active = 'fields'
 
        if request.POST:
 

	
 
            return redirect(url('repo_edit_fields'))
 
        return render('admin/repos/repo_edit.html')
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def create_repo_field(self, repo_name):
 
        try:
 
            form_result = RepoFieldForm()().to_python(dict(request.POST))
 
            new_field = RepositoryField()
 
            new_field.repository = Repository.get_by_repo_name(repo_name)
 
            new_field.field_key = form_result['new_field_key']
 
            new_field.field_type = form_result['new_field_type']  # python type
 
            new_field.field_value = form_result['new_field_value']  # set initial blank value
 
            new_field.field_desc = form_result['new_field_desc']
 
            new_field.field_label = form_result['new_field_label']
 
            Session().add(new_field)
 
            Session().commit()
 
        except Exception, e:
 
            log.error(traceback.format_exc())
 
            msg = _('An error occurred during creation of field')
 
            if isinstance(e, formencode.Invalid):
 
                msg += ". " + e.msg
 
            h.flash(msg, category='error')
 
        return redirect(url('edit_repo_fields', repo_name=repo_name))
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def delete_repo_field(self, repo_name, field_id):
 
        field = RepositoryField.get_or_404(field_id)
 
        try:
 
            Session().delete(field)
 
            Session().commit()
 
@@ -495,181 +495,181 @@ class ReposController(BaseRepoController
 
        c.active = 'advanced'
 
        if request.POST:
 
            return redirect(url('repo_edit_advanced'))
 
        return htmlfill.render(
 
            render('admin/repos/repo_edit.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False)
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def edit_advanced_journal(self, repo_name):
 
        """
 
        Set's this repository to be visible in public journal,
 
        in other words assing default user to follow this repo
 

	
 
        :param repo_name:
 
        """
 

	
 
        cur_token = request.POST.get('auth_token')
 
        token = get_token()
 
        if cur_token == token:
 
            try:
 
                repo_id = Repository.get_by_repo_name(repo_name).repo_id
 
                user_id = User.get_default_user().user_id
 
                self.scm_model.toggle_following_repo(repo_id, user_id)
 
                h.flash(_('Updated repository visibility in public journal'),
 
                        category='success')
 
                Session().commit()
 
            except Exception:
 
                h.flash(_('An error occurred during setting this'
 
                          ' repository in public journal'),
 
                        category='error')
 

	
 
        else:
 
            h.flash(_('Token mismatch'), category='error')
 
        return redirect(url('edit_repo_advanced', repo_name=repo_name))
 

	
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def edit_advanced_fork(self, repo_name):
 
        """
 
        Mark given repository as a fork of another
 

	
 
        :param repo_name:
 
        """
 
        try:
 
            fork_id = request.POST.get('id_fork_of')
 
            repo = ScmModel().mark_as_fork(repo_name, fork_id,
 
                                           self.rhodecode_user.username)
 
                                           self.authuser.username)
 
            fork = repo.fork.repo_name if repo.fork else _('Nothing')
 
            Session().commit()
 
            h.flash(_('Marked repo %s as fork of %s') % (repo_name, fork),
 
                    category='success')
 
        except RepositoryError, e:
 
            log.error(traceback.format_exc())
 
            h.flash(str(e), category='error')
 
        except Exception, e:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during this operation'),
 
                    category='error')
 

	
 
        return redirect(url('edit_repo_advanced', repo_name=repo_name))
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def edit_advanced_locking(self, repo_name):
 
        """
 
        Unlock repository when it is locked !
 

	
 
        :param repo_name:
 
        """
 
        try:
 
            repo = Repository.get_by_repo_name(repo_name)
 
            if request.POST.get('set_lock'):
 
                Repository.lock(repo, c.rhodecode_user.user_id)
 
                Repository.lock(repo, c.authuser.user_id)
 
                h.flash(_('Locked repository'), category='success')
 
            elif request.POST.get('set_unlock'):
 
                Repository.unlock(repo)
 
                h.flash(_('Unlocked repository'), category='success')
 
        except Exception, e:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during unlocking'),
 
                    category='error')
 
        return redirect(url('edit_repo_advanced', repo_name=repo_name))
 

	
 
    @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
 
    def toggle_locking(self, repo_name):
 
        """
 
        Toggle locking of repository by simple GET call to url
 

	
 
        :param repo_name:
 
        """
 

	
 
        try:
 
            repo = Repository.get_by_repo_name(repo_name)
 

	
 
            if repo.enable_locking:
 
                if repo.locked[0]:
 
                    Repository.unlock(repo)
 
                    action = _('Unlocked')
 
                else:
 
                    Repository.lock(repo, c.rhodecode_user.user_id)
 
                    Repository.lock(repo, c.authuser.user_id)
 
                    action = _('Locked')
 

	
 
                h.flash(_('Repository has been %s') % action,
 
                        category='success')
 
        except Exception, e:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during unlocking'),
 
                    category='error')
 
        return redirect(url('summary_home', repo_name=repo_name))
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def edit_caches(self, repo_name):
 
        """GET /repo_name/settings: Form to edit an existing item"""
 
        # url('edit_repo', repo_name=ID)
 
        c.repo_info = self._load_repo(repo_name)
 
        c.active = 'caches'
 
        if request.POST:
 
            try:
 
                ScmModel().mark_for_invalidation(repo_name, delete=True)
 
                Session().commit()
 
                h.flash(_('Cache invalidation successful'),
 
                        category='success')
 
            except Exception, e:
 
                log.error(traceback.format_exc())
 
                h.flash(_('An error occurred during cache invalidation'),
 
                        category='error')
 

	
 
            return redirect(url('edit_repo_caches', repo_name=c.repo_name))
 
        return render('admin/repos/repo_edit.html')
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def edit_remote(self, repo_name):
 
        """GET /repo_name/settings: Form to edit an existing item"""
 
        # url('edit_repo', repo_name=ID)
 
        c.repo_info = self._load_repo(repo_name)
 
        c.active = 'remote'
 
        if request.POST:
 
            try:
 
                ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
 
                ScmModel().pull_changes(repo_name, self.authuser.username)
 
                h.flash(_('Pulled from remote location'), category='success')
 
            except Exception, e:
 
                log.error(traceback.format_exc())
 
                h.flash(_('An error occurred during pull from remote location'),
 
                        category='error')
 
            return redirect(url('edit_repo_remote', repo_name=c.repo_name))
 
        return render('admin/repos/repo_edit.html')
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def edit_statistics(self, repo_name):
 
        """GET /repo_name/settings: Form to edit an existing item"""
 
        # url('edit_repo', repo_name=ID)
 
        c.repo_info = self._load_repo(repo_name)
 
        repo = c.repo_info.scm_instance
 

	
 
        if c.repo_info.stats:
 
            # this is on what revision we ended up so we add +1 for count
 
            last_rev = c.repo_info.stats.stat_on_revision + 1
 
        else:
 
            last_rev = 0
 
        c.stats_revision = last_rev
 

	
 
        c.repo_last_rev = repo.count() if repo.revisions else 0
 

	
 
        if last_rev == 0 or c.repo_last_rev == 0:
 
            c.stats_percentage = 0
 
        else:
 
            c.stats_percentage = '%.2f' % ((float((last_rev)) / c.repo_last_rev) * 100)
 

	
 
        c.active = 'statistics'
 
        if request.POST:
 
            try:
 
                RepoModel().delete_stats(repo_name)
 
                Session().commit()
 
            except Exception, e:
 
                log.error(traceback.format_exc())
 
                h.flash(_('An error occurred during deletion of repository stats'),
 
                        category='error')
 
            return redirect(url('edit_repo_statistics', repo_name=c.repo_name))
 

	
 
        return render('admin/repos/repo_edit.html')
kallithea/controllers/admin/user_groups.py
Show inline comments
 
@@ -93,150 +93,150 @@ class UserGroupsController(BaseControlle
 
                        .all()
 
        group_iter = UserGroupList(_list, perm_set=['usergroup.admin'])
 
        user_groups_data = []
 
        total_records = len(group_iter)
 
        _tmpl_lookup = kallithea.CONFIG['pylons.app_globals'].mako_lookup
 
        template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
 

	
 
        user_group_name = lambda user_group_id, user_group_name: (
 
            template.get_def("user_group_name")
 
            .render(user_group_id, user_group_name, _=_, h=h, c=c)
 
        )
 
        user_group_actions = lambda user_group_id, user_group_name: (
 
            template.get_def("user_group_actions")
 
            .render(user_group_id, user_group_name, _=_, h=h, c=c)
 
        )
 
        for user_gr in group_iter:
 

	
 
            user_groups_data.append({
 
                "raw_name": user_gr.users_group_name,
 
                "group_name": user_group_name(user_gr.users_group_id,
 
                                              user_gr.users_group_name),
 
                "desc": user_gr.user_group_description,
 
                "members": len(user_gr.members),
 
                "active": h.boolicon(user_gr.users_group_active),
 
                "owner": h.person(user_gr.user.username),
 
                "action": user_group_actions(user_gr.users_group_id, user_gr.users_group_name)
 
            })
 

	
 
        c.data = json.dumps({
 
            "totalRecords": total_records,
 
            "startIndex": 0,
 
            "sort": None,
 
            "dir": "asc",
 
            "records": user_groups_data
 
        })
 

	
 
        return render('admin/user_groups/user_groups.html')
 

	
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
 
    def create(self):
 
        """POST /users_groups: Create a new item"""
 
        # url('users_groups')
 

	
 
        users_group_form = UserGroupForm()()
 
        try:
 
            form_result = users_group_form.to_python(dict(request.POST))
 
            UserGroupModel().create(name=form_result['users_group_name'],
 
                                    description=form_result['user_group_description'],
 
                                    owner=self.rhodecode_user.user_id,
 
                                    owner=self.authuser.user_id,
 
                                    active=form_result['users_group_active'])
 

	
 
            gr = form_result['users_group_name']
 
            action_logger(self.rhodecode_user,
 
            action_logger(self.authuser,
 
                          'admin_created_users_group:%s' % gr,
 
                          None, self.ip_addr, self.sa)
 
            h.flash(_('Created user group %s') % gr, category='success')
 
            Session().commit()
 
        except formencode.Invalid, errors:
 
            return htmlfill.render(
 
                render('admin/user_groups/user_group_add.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 occurred during creation of user group %s') \
 
                    % request.POST.get('users_group_name'), category='error')
 

	
 
        return redirect(url('users_groups'))
 

	
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
 
    def new(self, format='html'):
 
        """GET /user_groups/new: Form to create a new item"""
 
        # url('new_users_group')
 
        return render('admin/user_groups/user_group_add.html')
 

	
 
    @HasUserGroupPermissionAnyDecorator('usergroup.admin')
 
    def update(self, id):
 
        """PUT /user_groups/id: 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('users_group', id=ID),
 
        #           method='put')
 
        # url('users_group', id=ID)
 

	
 
        c.user_group = UserGroup.get_or_404(id)
 
        c.active = 'settings'
 
        self.__load_data(id)
 

	
 
        available_members = [safe_unicode(x[0]) for x in c.available_members]
 

	
 
        users_group_form = UserGroupForm(edit=True,
 
                                         old_data=c.user_group.get_dict(),
 
                                         available_members=available_members)()
 

	
 
        try:
 
            form_result = users_group_form.to_python(request.POST)
 
            UserGroupModel().update(c.user_group, form_result)
 
            gr = form_result['users_group_name']
 
            action_logger(self.rhodecode_user,
 
            action_logger(self.authuser,
 
                          'admin_updated_users_group:%s' % gr,
 
                          None, self.ip_addr, self.sa)
 
            h.flash(_('Updated user group %s') % gr, category='success')
 
            Session().commit()
 
        except formencode.Invalid, errors:
 
            ug_model = UserGroupModel()
 
            defaults = errors.value
 
            e = errors.error_dict or {}
 
            defaults.update({
 
                'create_repo_perm': ug_model.has_perm(id,
 
                                                      'hg.create.repository'),
 
                'fork_repo_perm': ug_model.has_perm(id,
 
                                                    'hg.fork.repository'),
 
                '_method': 'put'
 
            })
 

	
 
            return htmlfill.render(
 
                render('admin/user_groups/user_group_edit.html'),
 
                defaults=defaults,
 
                errors=e,
 
                prefix_error=False,
 
                encoding="UTF-8")
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('Error occurred during update of user group %s') \
 
                    % request.POST.get('users_group_name'), category='error')
 

	
 
        return redirect(url('edit_users_group', id=id))
 

	
 
    @HasUserGroupPermissionAnyDecorator('usergroup.admin')
 
    def delete(self, id):
 
        """DELETE /user_groups/id: 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('users_group', id=ID),
 
        #           method='delete')
 
        # url('users_group', id=ID)
 
        usr_gr = UserGroup.get_or_404(id)
 
        try:
 
            UserGroupModel().delete(usr_gr)
 
            Session().commit()
 
            h.flash(_('Successfully deleted user group'), category='success')
 
        except UserGroupsAssignedException, e:
 
            h.flash(e, category='error')
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during deletion of user group'),
 
@@ -264,119 +264,119 @@ class UserGroupsController(BaseControlle
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )
 

	
 
    @HasUserGroupPermissionAnyDecorator('usergroup.admin')
 
    def edit_perms(self, id):
 
        c.user_group = UserGroup.get_or_404(id)
 
        c.active = 'perms'
 

	
 
        repo_model = RepoModel()
 
        c.users_array = repo_model.get_users_js()
 
        c.user_groups_array = repo_model.get_user_groups_js()
 

	
 
        defaults = {}
 
        # fill user group users
 
        for p in c.user_group.user_user_group_to_perm:
 
            defaults.update({'u_perm_%s' % p.user.username:
 
                             p.permission.permission_name})
 

	
 
        for p in c.user_group.user_group_user_group_to_perm:
 
            defaults.update({'g_perm_%s' % p.user_group.users_group_name:
 
                             p.permission.permission_name})
 

	
 
        return htmlfill.render(
 
            render('admin/user_groups/user_group_edit.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )
 

	
 
    @HasUserGroupPermissionAnyDecorator('usergroup.admin')
 
    def update_perms(self, id):
 
        """
 
        grant permission for given usergroup
 

	
 
        :param id:
 
        """
 
        user_group = UserGroup.get_or_404(id)
 
        form = UserGroupPermsForm()().to_python(request.POST)
 

	
 
        # set the permissions !
 
        try:
 
            UserGroupModel()._update_permissions(user_group, form['perms_new'],
 
                                                 form['perms_updates'])
 
        except RepoGroupAssignmentError:
 
            h.flash(_('Target group cannot be the same'), category='error')
 
            return redirect(url('edit_user_group_perms', id=id))
 
        #TODO: implement this
 
        #action_logger(self.rhodecode_user, 'admin_changed_repo_permissions',
 
        #action_logger(self.authuser, 'admin_changed_repo_permissions',
 
        #              repo_name, self.ip_addr, self.sa)
 
        Session().commit()
 
        h.flash(_('User Group permissions updated'), category='success')
 
        return redirect(url('edit_user_group_perms', id=id))
 

	
 
    @HasUserGroupPermissionAnyDecorator('usergroup.admin')
 
    def delete_perms(self, id):
 
        """
 
        DELETE an existing repository group permission user
 

	
 
        :param group_name:
 
        """
 
        try:
 
            obj_type = request.POST.get('obj_type')
 
            obj_id = None
 
            if obj_type == 'user':
 
                obj_id = safe_int(request.POST.get('user_id'))
 
            elif obj_type == 'user_group':
 
                obj_id = safe_int(request.POST.get('user_group_id'))
 

	
 
            if not c.rhodecode_user.is_admin:
 
                if obj_type == 'user' and c.rhodecode_user.user_id == obj_id:
 
            if not c.authuser.is_admin:
 
                if obj_type == 'user' and c.authuser.user_id == obj_id:
 
                    msg = _('Cannot revoke permission for yourself as admin')
 
                    h.flash(msg, category='warning')
 
                    raise Exception('revoke admin permission on self')
 
            if obj_type == 'user':
 
                UserGroupModel().revoke_user_permission(user_group=id,
 
                                                        user=obj_id)
 
            elif obj_type == 'user_group':
 
                UserGroupModel().revoke_user_group_permission(target_user_group=id,
 
                                                              user_group=obj_id)
 
            Session().commit()
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during revoking of permission'),
 
                    category='error')
 
            raise HTTPInternalServerError()
 

	
 
    @HasUserGroupPermissionAnyDecorator('usergroup.admin')
 
    def edit_default_perms(self, id):
 
        c.user_group = UserGroup.get_or_404(id)
 
        c.active = 'default_perms'
 

	
 
        permissions = {
 
            'repositories': {},
 
            'repositories_groups': {}
 
        }
 
        ugroup_repo_perms = UserGroupRepoToPerm.query()\
 
            .options(joinedload(UserGroupRepoToPerm.permission))\
 
            .options(joinedload(UserGroupRepoToPerm.repository))\
 
            .filter(UserGroupRepoToPerm.users_group_id == id)\
 
            .all()
 

	
 
        for gr in ugroup_repo_perms:
 
            permissions['repositories'][gr.repository.repo_name]  \
 
                = gr.permission.permission_name
 

	
 
        ugroup_group_perms = UserGroupRepoGroupToPerm.query()\
 
            .options(joinedload(UserGroupRepoGroupToPerm.permission))\
 
            .options(joinedload(UserGroupRepoGroupToPerm.group))\
 
            .filter(UserGroupRepoGroupToPerm.users_group_id == id)\
 
            .all()
 

	
 
        for gr in ugroup_group_perms:
 
            permissions['repositories_groups'][gr.group.group_name] \
 
                = gr.permission.permission_name
 
        c.permissions = permissions
 

	
 
        ug_model = UserGroupModel()
 

	
kallithea/controllers/admin/users.py
Show inline comments
 
@@ -83,150 +83,150 @@ class UsersController(BaseController):
 
                template.get_def("user_gravatar")
 
                .render(user_email, size, _=_, h=h, c=c))
 

	
 
        username = lambda user_id, username: (
 
                template.get_def("user_name")
 
                .render(user_id, username, _=_, h=h, c=c))
 

	
 
        user_actions = lambda user_id, username: (
 
                template.get_def("user_actions")
 
                .render(user_id, username, _=_, h=h, c=c))
 

	
 
        for user in c.users_list:
 

	
 
            users_data.append({
 
                "gravatar": grav_tmpl(user. email, 20),
 
                "raw_name": user.username,
 
                "username": username(user.user_id, user.username),
 
                "firstname": user.name,
 
                "lastname": user.lastname,
 
                "last_login": h.fmt_date(user.last_login),
 
                "last_login_raw": datetime_to_time(user.last_login),
 
                "active": h.boolicon(user.active),
 
                "admin": h.boolicon(user.admin),
 
                "extern_type": user.extern_type,
 
                "extern_name": user.extern_name,
 
                "action": user_actions(user.user_id, user.username),
 
            })
 

	
 
        c.data = json.dumps({
 
            "totalRecords": total_records,
 
            "startIndex": 0,
 
            "sort": None,
 
            "dir": "asc",
 
            "records": users_data
 
        })
 

	
 
        return render('admin/users/users.html')
 

	
 
    def create(self):
 
        """POST /users: Create a new item"""
 
        # url('users')
 
        c.default_extern_type = auth_modules.auth_rhodecode.RhodeCodeAuthPlugin.name
 
        user_model = UserModel()
 
        user_form = UserForm()()
 
        try:
 
            form_result = user_form.to_python(dict(request.POST))
 
            user_model.create(form_result)
 
            usr = form_result['username']
 
            action_logger(self.rhodecode_user, 'admin_created_user:%s' % usr,
 
            action_logger(self.authuser, 'admin_created_user:%s' % usr,
 
                          None, self.ip_addr, self.sa)
 
            h.flash(_('Created user %s') % usr,
 
                    category='success')
 
            Session().commit()
 
        except formencode.Invalid, errors:
 
            return htmlfill.render(
 
                render('admin/users/user_add.html'),
 
                defaults=errors.value,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8")
 
        except UserCreationError, e:
 
            h.flash(e, 'error')
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('Error occurred during creation of user %s') \
 
                    % request.POST.get('username'), category='error')
 
        return redirect(url('users'))
 

	
 
    def new(self, format='html'):
 
        """GET /users/new: Form to create a new item"""
 
        # url('new_user')
 
        c.default_extern_type = auth_modules.auth_rhodecode.RhodeCodeAuthPlugin.name
 
        return render('admin/users/user_add.html')
 

	
 
    def update(self, id):
 
        """PUT /users/id: 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('update_user', id=ID),
 
        #           method='put')
 
        # url('user', id=ID)
 
        c.active = 'profile'
 
        user_model = UserModel()
 
        c.user = user_model.get(id)
 
        c.extern_type = c.user.extern_type
 
        c.extern_name = c.user.extern_name
 
        c.perm_user = AuthUser(user_id=id, ip_addr=self.ip_addr)
 
        _form = UserForm(edit=True, old_data={'user_id': id,
 
                                              'email': c.user.email})()
 
        form_result = {}
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            skip_attrs = ['extern_type', 'extern_name']
 
            #TODO: plugin should define if username can be updated
 
            if c.extern_type != "rhodecode":
 
                # forbid updating username for external accounts
 
                skip_attrs.append('username')
 

	
 
            user_model.update(id, form_result, skip_attrs=skip_attrs)
 
            usr = form_result['username']
 
            action_logger(self.rhodecode_user, 'admin_updated_user:%s' % usr,
 
            action_logger(self.authuser, 'admin_updated_user:%s' % usr,
 
                          None, self.ip_addr, self.sa)
 
            h.flash(_('User updated successfully'), category='success')
 
            Session().commit()
 
        except formencode.Invalid, errors:
 
            defaults = errors.value
 
            e = errors.error_dict or {}
 
            defaults.update({
 
                'create_repo_perm': user_model.has_perm(id,
 
                                                        'hg.create.repository'),
 
                'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'),
 
                '_method': 'put'
 
            })
 
            return htmlfill.render(
 
                render('admin/users/user_edit.html'),
 
                defaults=defaults,
 
                errors=e,
 
                prefix_error=False,
 
                encoding="UTF-8")
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('Error occurred during update of user %s') \
 
                    % form_result.get('username'), category='error')
 
        return redirect(url('edit_user', id=id))
 

	
 
    def delete(self, id):
 
        """DELETE /users/id: 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('delete_user', id=ID),
 
        #           method='delete')
 
        # url('user', id=ID)
 
        usr = User.get_or_404(id)
 
        try:
 
            UserModel().delete(usr)
 
            Session().commit()
 
            h.flash(_('Successfully deleted user'), category='success')
 
        except (UserOwnsReposException, DefaultUserException), e:
 
            h.flash(e, category='warning')
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during deletion of user'),
 
                    category='error')
 
        return redirect(url('users'))
 

	
 
    def show(self, id, format='html'):
 
        """GET /users/id: Show a specific item"""
 
        # url('user', id=ID)
kallithea/controllers/api/__init__.py
Show inline comments
 
@@ -144,98 +144,98 @@ class JSONRPCController(WSGIController):
 

	
 
            log.debug(
 
                'method: %s, params: %s' % (self._req_method,
 
                                            self._request_params)
 
            )
 
        except KeyError, e:
 
            return jsonrpc_error(retid=self._req_id,
 
                                 message='Incorrect JSON query missing %s' % e)
 

	
 
        # check if we can find this session using api_key
 
        try:
 
            u = User.get_by_api_key(self._req_api_key)
 
            if u is None:
 
                return jsonrpc_error(retid=self._req_id,
 
                                     message='Invalid API KEY')
 

	
 
            #check if we are allowed to use this IP
 
            auth_u = AuthUser(u.user_id, self._req_api_key, ip_addr=ip_addr)
 
            if not auth_u.ip_allowed:
 
                return jsonrpc_error(retid=self._req_id,
 
                        message='request from IP:%s not allowed' % (ip_addr,))
 
            else:
 
                log.info('Access for IP:%s allowed' % (ip_addr,))
 

	
 
        except Exception, e:
 
            return jsonrpc_error(retid=self._req_id,
 
                                 message='Invalid API KEY')
 

	
 
        self._error = None
 
        try:
 
            self._func = self._find_method()
 
        except AttributeError, e:
 
            return jsonrpc_error(retid=self._req_id,
 
                                 message=str(e))
 

	
 
        # now that we have a method, add self._req_params to
 
        # self.kargs and dispatch control to WGIController
 
        argspec = inspect.getargspec(self._func)
 
        arglist = argspec[0][1:]
 
        defaults = map(type, argspec[3] or [])
 
        default_empty = types.NotImplementedType
 

	
 
        # kw arguments required by this method
 
        func_kwargs = dict(izip_longest(reversed(arglist), reversed(defaults),
 
                                        fillvalue=default_empty))
 

	
 
        # this is little trick to inject logged in user for
 
        # perms decorators to work they expect the controller class to have
 
        # rhodecode_user attribute set
 
        self.rhodecode_user = auth_u
 
        # authuser attribute set
 
        self.authuser = auth_u
 

	
 
        # This attribute will need to be first param of a method that uses
 
        # api_key, which is translated to instance of user at that name
 
        USER_SESSION_ATTR = 'apiuser'
 

	
 
        if USER_SESSION_ATTR not in arglist:
 
            return jsonrpc_error(
 
                retid=self._req_id,
 
                message='This method [%s] does not support '
 
                         'authentication (missing %s param)' % (
 
                                    self._func.__name__, USER_SESSION_ATTR)
 
            )
 

	
 
        # get our arglist and check if we provided them as args
 
        for arg, default in func_kwargs.iteritems():
 
            if arg == USER_SESSION_ATTR:
 
                # USER_SESSION_ATTR is something translated from api key and
 
                # this is checked before so we don't need validate it
 
                continue
 

	
 
            # skip the required param check if it's default value is
 
            # NotImplementedType (default_empty)
 
            if default == default_empty and arg not in self._request_params:
 
                return jsonrpc_error(
 
                    retid=self._req_id,
 
                    message=(
 
                        'Missing non optional `%s` arg in JSON DATA' % arg
 
                    )
 
                )
 

	
 
        self._rpc_args = {USER_SESSION_ATTR: u}
 

	
 
        self._rpc_args.update(self._request_params)
 

	
 
        self._rpc_args['action'] = self._req_method
 
        self._rpc_args['environ'] = environ
 
        self._rpc_args['start_response'] = start_response
 

	
 
        status = []
 
        headers = []
 
        exc_info = []
 

	
 
        def change_content(new_status, new_headers, new_exc_info=None):
 
            status.append(new_status)
 
            headers.extend(new_headers)
 
            exc_info.append(new_exc_info)
 

	
 
        output = WSGIController.__call__(self, environ, change_content)
kallithea/controllers/api/api.py
Show inline comments
 
@@ -151,97 +151,97 @@ class ApiController(JSONRPCController):
 

	
 
        def func(apiuser,arg1, arg2,...):
 
            pass
 

	
 
    Each function should also **raise** JSONRPCError for any
 
    errors that happens.
 

	
 
    """
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def test(self, apiuser, args):
 
        return args
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def pull(self, apiuser, repoid):
 
        """
 
        Triggers a pull from remote location on given repo. Can be used to
 
        automatically keep remote repos up to date. This command can be executed
 
        only using api_key belonging to user with admin rights
 

	
 
        :param apiuser: filled automatically from apikey
 
        :type apiuser: AuthUser
 
        :param repoid: repository name or repository id
 
        :type repoid: str or int
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            "msg": "Pulled from `<repository name>`"
 
            "repository": "<repository name>"
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "Unable to pull changes from `<reponame>`"
 
          }
 

	
 
        """
 

	
 
        repo = get_repo_or_error(repoid)
 

	
 
        try:
 
            ScmModel().pull_changes(repo.repo_name,
 
                                    self.rhodecode_user.username)
 
                                    self.authuser.username)
 
            return dict(
 
                msg='Pulled from `%s`' % repo.repo_name,
 
                repository=repo.repo_name
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'Unable to pull changes from `%s`' % repo.repo_name
 
            )
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def rescan_repos(self, apiuser, remove_obsolete=Optional(False)):
 
        """
 
        Triggers rescan repositories action. If remove_obsolete is set
 
        than also delete repos that are in database but not in the filesystem.
 
        aka "clean zombies". This command can be executed only using api_key
 
        belonging to user with admin rights.
 

	
 
        :param apiuser: filled automatically from apikey
 
        :type apiuser: AuthUser
 
        :param remove_obsolete: deletes repositories from
 
            database that are not found on the filesystem
 
        :type remove_obsolete: Optional(bool)
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            'added': [<added repository name>,...]
 
            'removed': [<removed repository name>,...]
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            'Error occurred during rescan repositories action'
 
          }
 

	
 
        """
 

	
 
        try:
 
            rm_obsolete = Optional.extract(remove_obsolete)
 
            added, removed = repo2db_mapper(ScmModel().repo_scan(),
 
                                            remove_obsolete=rm_obsolete)
 
            return {'added': added, 'removed': removed}
kallithea/controllers/changeset.py
Show inline comments
 
@@ -311,166 +311,166 @@ class ChangesetController(BaseRepoContro
 
            return diff
 
        elif method == 'show':
 
            self.__load_data()
 
            if len(c.cs_ranges) == 1:
 
                return render('changeset/changeset.html')
 
            else:
 
                return render('changeset/changeset_range.html')
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def index(self, revision, method='show'):
 
        return self._index(revision, method=method)
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def changeset_raw(self, revision):
 
        return self._index(revision, method='raw')
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def changeset_patch(self, revision):
 
        return self._index(revision, method='patch')
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def changeset_download(self, revision):
 
        return self._index(revision, method='download')
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    @jsonify
 
    def comment(self, repo_name, revision):
 
        status = request.POST.get('changeset_status')
 
        change_status = request.POST.get('change_changeset_status')
 
        text = request.POST.get('text')
 
        if status and change_status:
 
            text = text or (_('Status change -> %s')
 
                            % ChangesetStatus.get_status_lbl(status))
 

	
 
        c.co = comm = ChangesetCommentsModel().create(
 
            text=text,
 
            repo=c.db_repo.repo_id,
 
            user=c.rhodecode_user.user_id,
 
            user=c.authuser.user_id,
 
            revision=revision,
 
            f_path=request.POST.get('f_path'),
 
            line_no=request.POST.get('line'),
 
            status_change=(ChangesetStatus.get_status_lbl(status)
 
                           if status and change_status else None)
 
        )
 

	
 
        # get status if set !
 
        if status and change_status:
 
            # if latest status was from pull request and it's closed
 
            # disallow changing status !
 
            # dont_allow_on_closed_pull_request = True !
 

	
 
            try:
 
                ChangesetStatusModel().set_status(
 
                    c.db_repo.repo_id,
 
                    status,
 
                    c.rhodecode_user.user_id,
 
                    c.authuser.user_id,
 
                    comm,
 
                    revision=revision,
 
                    dont_allow_on_closed_pull_request=True
 
                )
 
            except StatusChangeOnClosedPullRequestError:
 
                log.error(traceback.format_exc())
 
                msg = _('Changing status on a changeset associated with '
 
                        'a closed pull request is not allowed')
 
                h.flash(msg, category='warning')
 
                return redirect(h.url('changeset_home', repo_name=repo_name,
 
                                      revision=revision))
 
        action_logger(self.rhodecode_user,
 
        action_logger(self.authuser,
 
                      'user_commented_revision:%s' % revision,
 
                      c.db_repo, self.ip_addr, self.sa)
 

	
 
        Session().commit()
 

	
 
        if not request.environ.get('HTTP_X_PARTIAL_XHR'):
 
            return redirect(h.url('changeset_home', repo_name=repo_name,
 
                                  revision=revision))
 
        #only ajax below
 
        data = {
 
           'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
 
        }
 
        if comm:
 
            data.update(comm.get_dict())
 
            data.update({'rendered_text':
 
                         render('changeset/changeset_comment_block.html')})
 

	
 
        return data
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def preview_comment(self):
 
        if not request.environ.get('HTTP_X_PARTIAL_XHR'):
 
            raise HTTPBadRequest()
 
        text = request.POST.get('text')
 
        if text:
 
            return h.rst_w_mentions(text)
 
        return ''
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    @jsonify
 
    def delete_comment(self, repo_name, comment_id):
 
        co = ChangesetComment.get(comment_id)
 
        owner = co.author.user_id == c.rhodecode_user.user_id
 
        owner = co.author.user_id == c.authuser.user_id
 
        repo_admin = h.HasRepoPermissionAny('repository.admin')
 
        if h.HasPermissionAny('hg.admin')() or repo_admin or owner:
 
            ChangesetCommentsModel().delete(comment=co)
 
            Session().commit()
 
            return True
 
        else:
 
            raise HTTPForbidden()
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    @jsonify
 
    def changeset_info(self, repo_name, revision):
 
        if request.is_xhr:
 
            try:
 
                return c.db_repo_scm_instance.get_changeset(revision)
 
            except ChangesetDoesNotExistError, e:
 
                return EmptyChangeset(message=str(e))
 
        else:
 
            raise HTTPBadRequest()
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    @jsonify
 
    def changeset_children(self, repo_name, revision):
 
        if request.is_xhr:
 
            changeset = c.db_repo_scm_instance.get_changeset(revision)
 
            result = {"results": []}
 
            if changeset.children:
 
                result = {"results": changeset.children}
 
            return result
 
        else:
 
            raise HTTPBadRequest()
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    @jsonify
 
    def changeset_parents(self, repo_name, revision):
 
        if request.is_xhr:
 
            changeset = c.db_repo_scm_instance.get_changeset(revision)
 
            result = {"results": []}
 
            if changeset.parents:
 
                result = {"results": changeset.parents}
 
            return result
 
        else:
 
            raise HTTPBadRequest()
kallithea/controllers/files.py
Show inline comments
 
@@ -277,250 +277,250 @@ class FilesController(BaseRepoController
 
                # do not just use the original mimetype, but force text/plain,
 
                # otherwise it would serve text/html and that might be unsafe.
 
                # Note: underlying vcs library fakes text/plain mimetype if the
 
                # mimetype can not be determined and it thinks it is not
 
                # binary.This might lead to erroneous text display in some
 
                # cases, but helps in other cases, like with text files
 
                # without extension.
 
                mimetype, dispo = 'text/plain', 'inline'
 

	
 
        if dispo == 'attachment':
 
            dispo = 'attachment; filename=%s' % \
 
                        safe_str(f_path.split(os.sep)[-1])
 

	
 
        response.content_disposition = dispo
 
        response.content_type = mimetype
 
        return file_node.content
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
 
    def delete(self, repo_name, revision, f_path):
 
        repo = c.db_repo
 
        if repo.enable_locking and repo.locked[0]:
 
            h.flash(_('This repository is has been locked by %s on %s')
 
                % (h.person_by_id(repo.locked[0]),
 
                   h.fmt_date(h.time_to_datetime(repo.locked[1]))),
 
                'warning')
 
            return redirect(h.url('files_home',
 
                                  repo_name=repo_name, revision='tip'))
 

	
 
        # check if revision is a branch identifier- basically we cannot
 
        # create multiple heads via file editing
 
        _branches = repo.scm_instance.branches
 
        # check if revision is a branch name or branch hash
 
        if revision not in _branches.keys() + _branches.values():
 
            h.flash(_('You can only delete files with revision '
 
                      'being a valid branch '), category='warning')
 
            return redirect(h.url('files_home',
 
                                  repo_name=repo_name, revision='tip',
 
                                  f_path=f_path))
 

	
 
        r_post = request.POST
 

	
 
        c.cs = self.__get_cs_or_redirect(revision, repo_name)
 
        c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
 

	
 
        c.default_message = _('Deleted file %s via RhodeCode') % (f_path)
 
        c.f_path = f_path
 
        node_path = f_path
 
        author = self.rhodecode_user.full_contact
 
        author = self.authuser.full_contact
 

	
 
        if r_post:
 
            message = r_post.get('message') or c.default_message
 

	
 
            try:
 
                nodes = {
 
                    node_path: {
 
                        'content': ''
 
                    }
 
                }
 
                self.scm_model.delete_nodes(
 
                    user=c.rhodecode_user.user_id, repo=c.db_repo,
 
                    user=c.authuser.user_id, repo=c.db_repo,
 
                    message=message,
 
                    nodes=nodes,
 
                    parent_cs=c.cs,
 
                    author=author,
 
                )
 

	
 
                h.flash(_('Successfully deleted file %s') % f_path,
 
                        category='success')
 
            except Exception:
 
                log.error(traceback.format_exc())
 
                h.flash(_('Error occurred during commit'), category='error')
 
            return redirect(url('changeset_home',
 
                                repo_name=c.repo_name, revision='tip'))
 

	
 
        return render('files/files_delete.html')
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
 
    def edit(self, repo_name, revision, f_path):
 
        repo = c.db_repo
 
        if repo.enable_locking and repo.locked[0]:
 
            h.flash(_('This repository is has been locked by %s on %s')
 
                % (h.person_by_id(repo.locked[0]),
 
                   h.fmt_date(h.time_to_datetime(repo.locked[1]))),
 
                'warning')
 
            return redirect(h.url('files_home',
 
                                  repo_name=repo_name, revision='tip'))
 

	
 
        # check if revision is a branch identifier- basically we cannot
 
        # create multiple heads via file editing
 
        _branches = repo.scm_instance.branches
 
        # check if revision is a branch name or branch hash
 
        if revision not in _branches.keys() + _branches.values():
 
            h.flash(_('You can only edit files with revision '
 
                      'being a valid branch '), category='warning')
 
            return redirect(h.url('files_home',
 
                                  repo_name=repo_name, revision='tip',
 
                                  f_path=f_path))
 

	
 
        r_post = request.POST
 

	
 
        c.cs = self.__get_cs_or_redirect(revision, repo_name)
 
        c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
 

	
 
        if c.file.is_binary:
 
            return redirect(url('files_home', repo_name=c.repo_name,
 
                            revision=c.cs.raw_id, f_path=f_path))
 
        c.default_message = _('Edited file %s via RhodeCode') % (f_path)
 
        c.f_path = f_path
 

	
 
        if r_post:
 

	
 
            old_content = c.file.content
 
            sl = old_content.splitlines(1)
 
            first_line = sl[0] if sl else ''
 
            # modes:  0 - Unix, 1 - Mac, 2 - DOS
 
            mode = detect_mode(first_line, 0)
 
            content = convert_line_endings(r_post.get('content', ''), mode)
 

	
 
            message = r_post.get('message') or c.default_message
 
            author = self.rhodecode_user.full_contact
 
            author = self.authuser.full_contact
 

	
 
            if content == old_content:
 
                h.flash(_('No changes'), category='warning')
 
                return redirect(url('changeset_home', repo_name=c.repo_name,
 
                                    revision='tip'))
 
            try:
 
                self.scm_model.commit_change(repo=c.db_repo_scm_instance,
 
                                             repo_name=repo_name, cs=c.cs,
 
                                             user=self.rhodecode_user.user_id,
 
                                             user=self.authuser.user_id,
 
                                             author=author, message=message,
 
                                             content=content, f_path=f_path)
 
                h.flash(_('Successfully committed to %s') % f_path,
 
                        category='success')
 
            except Exception:
 
                log.error(traceback.format_exc())
 
                h.flash(_('Error occurred during commit'), category='error')
 
            return redirect(url('changeset_home',
 
                                repo_name=c.repo_name, revision='tip'))
 

	
 
        return render('files/files_edit.html')
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
 
    def add(self, repo_name, revision, f_path):
 

	
 
        repo = Repository.get_by_repo_name(repo_name)
 
        if repo.enable_locking and repo.locked[0]:
 
            h.flash(_('This repository is has been locked by %s on %s')
 
                % (h.person_by_id(repo.locked[0]),
 
                   h.fmt_date(h.time_to_datetime(repo.locked[1]))),
 
                  'warning')
 
            return redirect(h.url('files_home',
 
                                  repo_name=repo_name, revision='tip'))
 

	
 
        r_post = request.POST
 
        c.cs = self.__get_cs_or_redirect(revision, repo_name,
 
                                         redirect_after=False)
 
        if c.cs is None:
 
            c.cs = EmptyChangeset(alias=c.db_repo_scm_instance.alias)
 
        c.default_message = (_('Added file via RhodeCode'))
 
        c.f_path = f_path
 

	
 
        if r_post:
 
            unix_mode = 0
 
            content = convert_line_endings(r_post.get('content', ''), unix_mode)
 

	
 
            message = r_post.get('message') or c.default_message
 
            filename = r_post.get('filename')
 
            location = r_post.get('location', '')
 
            file_obj = r_post.get('upload_file', None)
 

	
 
            if file_obj is not None and hasattr(file_obj, 'filename'):
 
                filename = file_obj.filename
 
                content = file_obj.file
 

	
 
                if hasattr(content, 'file'):
 
                    # non posix systems store real file under file attr
 
                    content = content.file
 

	
 
            if not content:
 
                h.flash(_('No content'), category='warning')
 
                return redirect(url('changeset_home', repo_name=c.repo_name,
 
                                    revision='tip'))
 
            if not filename:
 
                h.flash(_('No filename'), category='warning')
 
                return redirect(url('changeset_home', repo_name=c.repo_name,
 
                                    revision='tip'))
 
            #strip all crap out of file, just leave the basename
 
            filename = os.path.basename(filename)
 
            node_path = os.path.join(location, filename)
 
            author = self.rhodecode_user.full_contact
 
            author = self.authuser.full_contact
 

	
 
            try:
 
                nodes = {
 
                    node_path: {
 
                        'content': content
 
                    }
 
                }
 
                self.scm_model.create_nodes(
 
                    user=c.rhodecode_user.user_id, repo=c.db_repo,
 
                    user=c.authuser.user_id, repo=c.db_repo,
 
                    message=message,
 
                    nodes=nodes,
 
                    parent_cs=c.cs,
 
                    author=author,
 
                )
 

	
 
                h.flash(_('Successfully committed to %s') % node_path,
 
                        category='success')
 
            except NonRelativePathError, e:
 
                h.flash(_('Location must be relative path and must not '
 
                          'contain .. in path'), category='warning')
 
                return redirect(url('changeset_home', repo_name=c.repo_name,
 
                                    revision='tip'))
 
            except (NodeError, NodeAlreadyExistsError), e:
 
                h.flash(_(e), category='error')
 
            except Exception:
 
                log.error(traceback.format_exc())
 
                h.flash(_('Error occurred during commit'), category='error')
 
            return redirect(url('changeset_home',
 
                                repo_name=c.repo_name, revision='tip'))
 

	
 
        return render('files/files_add.html')
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def archivefile(self, repo_name, fname):
 

	
 
        fileformat = None
 
        revision = None
 
        ext = None
 
        subrepos = request.GET.get('subrepos') == 'true'
 

	
 
        for a_type, ext_data in settings.ARCHIVE_SPECS.items():
 
            archive_spec = fname.split(ext_data[1])
 
            if len(archive_spec) == 2 and archive_spec[1] == '':
 
                fileformat = a_type or ext_data[1]
 
                revision = archive_spec[0]
 
                ext = ext_data[1]
 

	
 
        try:
 
            dbrepo = RepoModel().get_by_repo_name(repo_name)
 
            if not dbrepo.enable_downloads:
 
                return _('Downloads disabled')
 

	
 
            if c.db_repo_scm_instance.alias == 'hg':
 
                # patch and reset hooks section of UI config to not run any
 
                # hooks on fetching archives with subrepos
 
@@ -541,97 +541,97 @@ class FilesController(BaseRepoController
 
        archive_name = '%s-%s%s' % (safe_str(repo_name.replace('/', '_')),
 
                                    safe_str(rev_name), ext)
 

	
 
        use_cached_archive = False  # defines if we use cached version of archive
 
        archive_cache_enabled = CONFIG.get('archive_cache_dir')
 
        if not subrepos and archive_cache_enabled:
 
            #check if we it's ok to write
 
            if not os.path.isdir(CONFIG['archive_cache_dir']):
 
                os.makedirs(CONFIG['archive_cache_dir'])
 
            cached_archive_path = os.path.join(CONFIG['archive_cache_dir'], archive_name)
 
            if os.path.isfile(cached_archive_path):
 
                log.debug('Found cached archive in %s' % cached_archive_path)
 
                fd, archive = None, cached_archive_path
 
                use_cached_archive = True
 
            else:
 
                log.debug('Archive %s is not yet cached' % (archive_name))
 

	
 
        if not use_cached_archive:
 
            # generate new archive
 
            temp_stream = None
 
            try:
 
                fd, archive = tempfile.mkstemp()
 
                temp_stream = open(archive, 'wb')
 
                log.debug('Creating new temp archive in %s' % archive)
 
                cs.fill_archive(stream=temp_stream, kind=fileformat, subrepos=subrepos)
 
                if not subrepos and archive_cache_enabled:
 
                    #if we generated the archive and use cache rename that
 
                    log.debug('Storing new archive in %s' % cached_archive_path)
 
                    shutil.move(archive, cached_archive_path)
 
                    archive = cached_archive_path
 
            finally:
 
                if temp_stream:
 
                    temp_stream.close()
 

	
 
        def get_chunked_archive(archive):
 
            stream = open(archive, 'rb')
 
            while True:
 
                data = stream.read(16 * 1024)
 
                if not data:
 
                    stream.close()
 
                    if fd:  # fd means we used temporary file
 
                        os.close(fd)
 
                    if not archive_cache_enabled:
 
                        log.debug('Destroing temp archive %s' % archive)
 
                        os.remove(archive)
 
                    break
 
                yield data
 
        # store download action
 
        action_logger(user=c.rhodecode_user,
 
        action_logger(user=c.authuser,
 
                      action='user_downloaded_archive:%s' % (archive_name),
 
                      repo=repo_name, ipaddr=self.ip_addr, commit=True)
 
        response.content_disposition = str('attachment; filename=%s' % (archive_name))
 
        response.content_type = str(content_type)
 
        return get_chunked_archive(archive)
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def diff(self, repo_name, f_path):
 
        ignore_whitespace = request.GET.get('ignorews') == '1'
 
        line_context = request.GET.get('context', 3)
 
        diff1 = request.GET.get('diff1', '')
 
        diff2 = request.GET.get('diff2', '')
 
        c.action = request.GET.get('diff')
 
        c.no_changes = diff1 == diff2
 
        c.f_path = f_path
 
        c.big_diff = False
 
        c.anchor_url = anchor_url
 
        c.ignorews_url = _ignorews_url
 
        c.context_url = _context_url
 
        c.changes = OrderedDict()
 
        c.changes[diff2] = []
 

	
 
        #special case if we want a show rev only, it's impl here
 
        #to reduce JS and callbacks
 

	
 
        if request.GET.get('show_rev'):
 
            if str2bool(request.GET.get('annotate', 'False')):
 
                _url = url('files_annotate_home', repo_name=c.repo_name,
 
                           revision=diff1, f_path=c.f_path)
 
            else:
 
                _url = url('files_home', repo_name=c.repo_name,
 
                           revision=diff1, f_path=c.f_path)
 

	
 
            return redirect(_url)
 
        try:
 
            if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
 
                c.changeset_1 = c.db_repo_scm_instance.get_changeset(diff1)
 
                try:
 
                    node1 = c.changeset_1.get_node(f_path)
 
                    if node1.is_dir():
 
                        raise NodeError('%s path is a %s not a file'
 
                                        % (node1, type(node1)))
 
                except NodeDoesNotExistError:
 
                    c.changeset_1 = EmptyChangeset(cs=diff1,
 
                                                   revision=c.changeset_1.revision,
 
                                                   repo=c.db_repo_scm_instance)
kallithea/controllers/forks.py
Show inline comments
 
@@ -127,68 +127,68 @@ class ForksController(BaseRepoController
 

	
 
        if request.environ.get('HTTP_X_PARTIAL_XHR'):
 
            return c.forks_data
 

	
 
        return render('/forks/forks.html')
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def fork(self, repo_name):
 
        c.repo_info = Repository.get_by_repo_name(repo_name)
 
        if not c.repo_info:
 
            h.not_mapped_error(repo_name)
 
            return redirect(url('home'))
 

	
 
        defaults = self.__load_data(repo_name)
 

	
 
        return htmlfill.render(
 
            render('forks/fork.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def fork_create(self, repo_name):
 
        self.__load_defaults()
 
        c.repo_info = Repository.get_by_repo_name(repo_name)
 
        _form = RepoForkForm(old_data={'repo_type': c.repo_info.repo_type},
 
                             repo_groups=c.repo_groups_choices,
 
                             landing_revs=c.landing_revs_choices)()
 
        form_result = {}
 
        task_id = None
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 

	
 
            # an approximation that is better than nothing
 
            if not RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_UPDATE).ui_active:
 
                form_result['update_after_clone'] = False
 

	
 
            # create fork is done sometimes async on celery, db transaction
 
            # management is handled there.
 
            task = RepoModel().create_fork(form_result, self.rhodecode_user.user_id)
 
            task = RepoModel().create_fork(form_result, self.authuser.user_id)
 
            from celery.result import BaseAsyncResult
 
            if isinstance(task, BaseAsyncResult):
 
                task_id = task.task_id
 
        except formencode.Invalid, errors:
 
            c.new_repo = errors.value['repo_name']
 
            return htmlfill.render(
 
                render('forks/fork.html'),
 
                defaults=errors.value,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8")
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during repository forking %s') %
 
                    repo_name, category='error')
 

	
 
        return redirect(h.url('repo_creating_home',
 
                              repo_name=form_result['repo_name_full'],
 
                              task_id=task_id))
kallithea/controllers/journal.py
Show inline comments
 
@@ -151,231 +151,231 @@ class JournalController(BaseController):
 
    def _rss_feed(self, repos, public=True):
 
        journal = self._get_journal_data(repos)
 
        if public:
 
            _link = url('public_journal_atom', qualified=True)
 
            _desc = '%s %s %s' % (c.rhodecode_name, _('public journal'),
 
                                  'rss feed')
 
        else:
 
            _link = url('journal_atom', qualified=True)
 
            _desc = '%s %s %s' % (c.rhodecode_name, _('journal'), 'rss feed')
 

	
 
        feed = Rss201rev2Feed(title=_desc,
 
                         link=_link,
 
                         description=_desc,
 
                         language=self.language,
 
                         ttl=self.ttl)
 

	
 
        for entry in journal[:self.feed_nr]:
 
            user = entry.user
 
            if user is None:
 
                #fix deleted users
 
                user = AttributeDict({'short_contact': entry.username,
 
                                      'email': '',
 
                                      'full_contact': ''})
 
            action, action_extra, ico = h.action_parser(entry, feed=True)
 
            title = "%s - %s %s" % (user.short_contact, action(),
 
                                    entry.repository.repo_name)
 
            desc = action_extra()
 
            _url = None
 
            if entry.repository is not None:
 
                _url = url('changelog_home',
 
                           repo_name=entry.repository.repo_name,
 
                           qualified=True)
 

	
 
            feed.add_item(title=title,
 
                          pubdate=entry.action_date,
 
                          link=_url or url('', qualified=True),
 
                          author_email=user.email,
 
                          author_name=user.full_contact,
 
                          description=desc)
 

	
 
        response.content_type = feed.mime_type
 
        return feed.writeString('utf-8')
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    def index(self):
 
        # Return a rendered template
 
        p = safe_int(request.GET.get('page', 1), 1)
 
        c.user = User.get(self.rhodecode_user.user_id)
 
        c.user = User.get(self.authuser.user_id)
 
        c.following = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
 
            .filter(UserFollowing.user_id == self.authuser.user_id)\
 
            .options(joinedload(UserFollowing.follows_repository))\
 
            .all()
 

	
 
        journal = self._get_journal_data(c.following)
 

	
 
        def url_generator(**kw):
 
            return url.current(filter=c.search_term, **kw)
 

	
 
        c.journal_pager = Page(journal, page=p, items_per_page=20, url=url_generator)
 
        c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
 

	
 
        c.journal_data = render('journal/journal_data.html')
 
        if request.environ.get('HTTP_X_PARTIAL_XHR'):
 
            return c.journal_data
 

	
 
        repos_list = Session().query(Repository)\
 
                     .filter(Repository.user_id ==
 
                             self.rhodecode_user.user_id)\
 
                             self.authuser.user_id)\
 
                     .order_by(func.lower(Repository.repo_name)).all()
 

	
 
        repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list,
 
                                                   admin=True)
 
        #json used to render the grid
 
        c.data = json.dumps(repos_data)
 

	
 
        watched_repos_data = []
 

	
 
        ## watched repos
 
        _render = RepoModel._render_datatable
 

	
 
        def quick_menu(repo_name):
 
            return _render('quick_menu', repo_name)
 

	
 
        def repo_lnk(name, rtype, rstate, private, fork_of):
 
            return _render('repo_name', name, rtype, rstate, private, fork_of,
 
                           short_name=False, admin=False)
 

	
 
        def last_rev(repo_name, cs_cache):
 
            return _render('revision', repo_name, cs_cache.get('revision'),
 
                           cs_cache.get('raw_id'), cs_cache.get('author'),
 
                           cs_cache.get('message'))
 

	
 
        def desc(desc):
 
            from pylons import tmpl_context as c
 
            if c.visual.stylify_metatags:
 
                return h.urlify_text(h.desc_stylize(h.truncate(desc, 60)))
 
            else:
 
                return h.urlify_text(h.truncate(desc, 60))
 

	
 
        def repo_actions(repo_name):
 
            return _render('repo_actions', repo_name)
 

	
 
        def owner_actions(user_id, username):
 
            return _render('user_name', user_id, username)
 

	
 
        def toogle_follow(repo_id):
 
            return  _render('toggle_follow', repo_id)
 

	
 
        for entry in c.following:
 
            repo = entry.follows_repository
 
            cs_cache = repo.changeset_cache
 
            row = {
 
                "menu": quick_menu(repo.repo_name),
 
                "raw_name": repo.repo_name.lower(),
 
                "name": repo_lnk(repo.repo_name, repo.repo_type,
 
                                 repo.repo_state, repo.private, repo.fork),
 
                "last_changeset": last_rev(repo.repo_name, cs_cache),
 
                "last_rev_raw": cs_cache.get('revision'),
 
                "action": toogle_follow(repo.repo_id)
 
            }
 

	
 
            watched_repos_data.append(row)
 

	
 
        c.watched_data = json.dumps({
 
            "totalRecords": len(c.following),
 
            "startIndex": 0,
 
            "sort": "name",
 
            "dir": "asc",
 
            "records": watched_repos_data
 
        })
 
        return render('journal/journal.html')
 

	
 
    @LoginRequired(api_access=True)
 
    @NotAnonymous()
 
    def journal_atom(self):
 
        """
 
        Produce an atom-1.0 feed via feedgenerator module
 
        """
 
        following = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
 
            .filter(UserFollowing.user_id == self.authuser.user_id)\
 
            .options(joinedload(UserFollowing.follows_repository))\
 
            .all()
 
        return self._atom_feed(following, public=False)
 

	
 
    @LoginRequired(api_access=True)
 
    @NotAnonymous()
 
    def journal_rss(self):
 
        """
 
        Produce an rss feed via feedgenerator module
 
        """
 
        following = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
 
            .filter(UserFollowing.user_id == self.authuser.user_id)\
 
            .options(joinedload(UserFollowing.follows_repository))\
 
            .all()
 
        return self._rss_feed(following, public=False)
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    def toggle_following(self):
 
        cur_token = request.POST.get('auth_token')
 
        token = h.get_token()
 
        if cur_token == token:
 

	
 
            user_id = request.POST.get('follows_user_id')
 
            if user_id:
 
                try:
 
                    self.scm_model.toggle_following_user(user_id,
 
                                                self.rhodecode_user.user_id)
 
                                                self.authuser.user_id)
 
                    Session.commit()
 
                    return 'ok'
 
                except Exception:
 
                    raise HTTPBadRequest()
 

	
 
            repo_id = request.POST.get('follows_repo_id')
 
            if repo_id:
 
                try:
 
                    self.scm_model.toggle_following_repo(repo_id,
 
                                                self.rhodecode_user.user_id)
 
                                                self.authuser.user_id)
 
                    Session.commit()
 
                    return 'ok'
 
                except Exception:
 
                    raise HTTPBadRequest()
 

	
 
        log.debug('token mismatch %s vs %s' % (cur_token, token))
 
        raise HTTPBadRequest()
 

	
 
    @LoginRequired()
 
    def public_journal(self):
 
        # Return a rendered template
 
        p = safe_int(request.GET.get('page', 1), 1)
 

	
 
        c.following = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
 
            .filter(UserFollowing.user_id == self.authuser.user_id)\
 
            .options(joinedload(UserFollowing.follows_repository))\
 
            .all()
 

	
 
        journal = self._get_journal_data(c.following)
 

	
 
        c.journal_pager = Page(journal, page=p, items_per_page=20)
 

	
 
        c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
 

	
 
        c.journal_data = render('journal/journal_data.html')
 
        if request.environ.get('HTTP_X_PARTIAL_XHR'):
 
            return c.journal_data
 
        return render('journal/public_journal.html')
 

	
 
    @LoginRequired(api_access=True)
 
    def public_journal_atom(self):
 
        """
 
        Produce an atom-1.0 feed via feedgenerator module
 
        """
 
        c.following = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
 
            .filter(UserFollowing.user_id == self.authuser.user_id)\
 
            .options(joinedload(UserFollowing.follows_repository))\
 
            .all()
 

	
 
        return self._atom_feed(c.following)
 

	
 
    @LoginRequired(api_access=True)
 
    def public_journal_rss(self):
 
        """
 
        Produce an rss2 feed via feedgenerator module
 
        """
 
        c.following = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
 
            .filter(UserFollowing.user_id == self.authuser.user_id)\
 
            .options(joinedload(UserFollowing.follows_repository))\
 
            .all()
 

	
 
        return self._rss_feed(c.following)
kallithea/controllers/login.py
Show inline comments
 
@@ -14,147 +14,147 @@
 
"""
 
kallithea.controllers.login
 
~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
Login controller for rhodeocode
 

	
 
:created_on: Apr 22, 2010
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH.
 
:license: GPLv3, see LICENSE for more details.
 
"""
 

	
 

	
 
import logging
 
import formencode
 
import datetime
 
import urlparse
 

	
 
from formencode import htmlfill
 
from webob.exc import HTTPFound
 
from pylons.i18n.translation import _
 
from pylons.controllers.util import redirect
 
from pylons import request, session, tmpl_context as c, url
 

	
 
import kallithea.lib.helpers as h
 
from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator
 
from kallithea.lib.auth_modules import importplugin
 
from kallithea.lib.base import BaseController, render
 
from kallithea.lib.exceptions import UserCreationError
 
from kallithea.model.db import User, RhodeCodeSetting
 
from kallithea.model.forms import LoginForm, RegisterForm, PasswordResetForm
 
from kallithea.model.user import UserModel
 
from kallithea.model.meta import Session
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class LoginController(BaseController):
 

	
 
    def __before__(self):
 
        super(LoginController, self).__before__()
 

	
 
    def _store_user_in_session(self, username, remember=False):
 
        user = User.get_by_username(username, case_insensitive=True)
 
        auth_user = AuthUser(user.user_id)
 
        auth_user.set_authenticated()
 
        cs = auth_user.get_cookie_store()
 
        session['rhodecode_user'] = cs
 
        session['authuser'] = cs
 
        user.update_lastlogin()
 
        Session().commit()
 

	
 
        # If they want to be remembered, update the cookie
 
        if remember:
 
            _year = (datetime.datetime.now() +
 
                     datetime.timedelta(seconds=60 * 60 * 24 * 365))
 
            session._set_cookie_expires(_year)
 

	
 
        session.save()
 

	
 
        log.info('user %s is now authenticated and stored in '
 
                 'session, session attrs %s' % (username, cs))
 

	
 
        # dumps session attrs back to cookie
 
        session._update_cookie_out()
 
        # we set new cookie
 
        headers = None
 
        if session.request['set_cookie']:
 
            # send set-cookie headers back to response to update cookie
 
            headers = [('Set-Cookie', session.request['cookie_out'])]
 
        return headers
 

	
 
    def _validate_came_from(self, came_from):
 
        if not came_from:
 
            return came_from
 

	
 
        parsed = urlparse.urlparse(came_from)
 
        server_parsed = urlparse.urlparse(url.current())
 
        allowed_schemes = ['http', 'https']
 
        if parsed.scheme and parsed.scheme not in allowed_schemes:
 
            log.error('Suspicious URL scheme detected %s for url %s' %
 
                     (parsed.scheme, parsed))
 
            came_from = url('home')
 
        elif server_parsed.netloc != parsed.netloc:
 
            log.error('Suspicious NETLOC detected %s for url %s server url '
 
                      'is: %s' % (parsed.netloc, parsed, server_parsed))
 
            came_from = url('home')
 
        return came_from
 

	
 
    def index(self):
 
        _default_came_from = url('home')
 
        came_from = self._validate_came_from(request.GET.get('came_from'))
 
        c.came_from = came_from or _default_came_from
 

	
 
        not_default = self.rhodecode_user.username != User.DEFAULT_USER
 
        ip_allowed = self.rhodecode_user.ip_allowed
 
        not_default = self.authuser.username != User.DEFAULT_USER
 
        ip_allowed = self.authuser.ip_allowed
 

	
 
        # redirect if already logged in
 
        if self.rhodecode_user.is_authenticated and not_default and ip_allowed:
 
        if self.authuser.is_authenticated and not_default and ip_allowed:
 
            raise HTTPFound(location=c.came_from)
 

	
 
        if request.POST:
 
            # import Login Form validator class
 
            login_form = LoginForm()
 
            try:
 
                session.invalidate()
 
                c.form_result = login_form.to_python(dict(request.POST))
 
                # form checks for username/password, now we're authenticated
 
                headers = self._store_user_in_session(
 
                                        username=c.form_result['username'],
 
                                        remember=c.form_result['remember'])
 
                raise HTTPFound(location=c.came_from, headers=headers)
 
            except formencode.Invalid, errors:
 
                defaults = errors.value
 
                # remove password from filling in form again
 
                del defaults['password']
 
                return htmlfill.render(
 
                    render('/login.html'),
 
                    defaults=errors.value,
 
                    errors=errors.error_dict or {},
 
                    prefix_error=False,
 
                    encoding="UTF-8")
 
            except UserCreationError, e:
 
                # container auth or other auth functions that create users on
 
                # the fly can throw this exception signaling that there's issue
 
                # with user creation, explanation should be provided in
 
                # Exception itself
 
                h.flash(e, 'error')
 

	
 
        # check if we use container plugin, and try to login using it.
 
        auth_plugins = RhodeCodeSetting.get_auth_plugins()
 
        if any((importplugin(name).is_container_auth for name in auth_plugins)):
 
            from kallithea.lib import auth_modules
 
            try:
 
                auth_info = auth_modules.authenticate('', '', request.environ)
 
            except UserCreationError, e:
 
                log.error(e)
 
                h.flash(e, 'error')
 
                # render login, with flash message about limit
 
                return render('/login.html')
 

	
 
            if auth_info:
 
                headers = self._store_user_in_session(auth_info.get('username'))
 
                raise HTTPFound(location=c.came_from, headers=headers)
 
        return render('/login.html')
 

	
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate',
kallithea/controllers/pullrequests.py
Show inline comments
 
@@ -116,100 +116,100 @@ class PullrequestsController(BaseRepoCon
 
                branches.append((selected, branch))
 

	
 
        bookmarks = []
 
        for bookmark, bookmarkrev in repo.bookmarks.iteritems():
 
            n = 'book:%s:%s' % (bookmark, bookmarkrev)
 
            bookmarks.append((n, bookmark))
 
            if rev == bookmarkrev:
 
                selected = n
 

	
 
        tags = []
 
        for tag, tagrev in repo.tags.iteritems():
 
            n = 'tag:%s:%s' % (tag, tagrev)
 
            tags.append((n, tag))
 
            if rev == tagrev and tag != 'tip':  # tip is not a real tag - and its branch is better
 
                selected = n
 

	
 
        # prio 1: rev was selected as existing entry above
 

	
 
        # prio 2: create special entry for rev; rev _must_ be used
 
        specials = []
 
        if rev and selected is None:
 
            selected = 'rev:%s:%s' % (rev, rev)
 
            specials = [(selected, '%s: %s' % (_("Changeset"), rev[:12]))]
 

	
 
        # prio 3: most recent peer branch
 
        if peers and not selected:
 
            selected = peers[0][0][0]
 

	
 
        # prio 4: tip revision
 
        if not selected:
 
            if h.is_hg(repo):
 
                selected = 'tag:tip:%s' % repo.tags['tip']
 
            else:
 
                if 'master' in repo.branches:
 
                    selected = 'branch:master:%s' % repo.branches['master']
 
                else:
 
                    k, v = repo.branches.items()[0]
 
                    selected = 'branch:%s:%s' % (k, v)
 

	
 
        groups = [(specials, _("Special")),
 
                  (peers, _("Peer branches")),
 
                  (bookmarks, _("Bookmarks")),
 
                  (branches, _("Branches")),
 
                  (tags, _("Tags")),
 
                  ]
 
        return [g for g in groups if g[0]], selected
 

	
 
    def _get_is_allowed_change_status(self, pull_request):
 
        owner = self.rhodecode_user.user_id == pull_request.user_id
 
        reviewer = self.rhodecode_user.user_id in [x.user_id for x in
 
        owner = self.authuser.user_id == pull_request.user_id
 
        reviewer = self.authuser.user_id in [x.user_id for x in
 
                                                   pull_request.reviewers]
 
        return self.rhodecode_user.admin or owner or reviewer
 
        return self.authuser.admin or owner or reviewer
 

	
 
    def _load_compare_data(self, pull_request, enable_comments=True):
 
        """
 
        Load context data needed for generating compare diff
 

	
 
        :param pull_request:
 
        """
 
        org_repo = pull_request.org_repo
 
        (org_ref_type,
 
         org_ref_name,
 
         org_ref_rev) = pull_request.org_ref.split(':')
 

	
 
        other_repo = org_repo
 
        (other_ref_type,
 
         other_ref_name,
 
         other_ref_rev) = pull_request.other_ref.split(':')
 

	
 
        # despite opening revisions for bookmarks/branches/tags, we always
 
        # convert this to rev to prevent changes after bookmark or branch change
 
        org_ref = ('rev', org_ref_rev)
 
        other_ref = ('rev', other_ref_rev)
 

	
 
        c.org_repo = org_repo
 
        c.other_repo = other_repo
 

	
 
        c.fulldiff = fulldiff = request.GET.get('fulldiff')
 

	
 
        c.cs_ranges = [org_repo.get_changeset(x) for x in pull_request.revisions]
 

	
 
        c.statuses = org_repo.statuses([x.raw_id for x in c.cs_ranges])
 

	
 
        c.org_ref = org_ref[1]
 
        c.org_ref_type = org_ref[0]
 
        c.other_ref = other_ref[1]
 
        c.other_ref_type = other_ref[0]
 

	
 
        diff_limit = self.cut_off_limit if not fulldiff else None
 

	
 
        # we swap org/other ref since we run a simple diff on one repo
 
        log.debug('running diff between %s and %s in %s'
 
                  % (other_ref, org_ref, org_repo.scm_instance.path))
 
        txtdiff = org_repo.scm_instance.get_diff(rev1=safe_str(other_ref[1]), rev2=safe_str(org_ref[1]))
 

	
 
        diff_processor = diffs.DiffProcessor(txtdiff or '', format='gitdiff',
 
                                             diff_limit=diff_limit)
 
        _parsed = diff_processor.prepare()
 

	
 
        c.limited_diff = False
 
@@ -300,260 +300,260 @@ class PullrequestsController(BaseRepoCon
 
        # gather forks and add to this list ... even though it is rare to
 
        # request forks to pull from their parent
 
        for fork in org_repo.forks:
 
            add_other_repo(fork)
 

	
 
        # add parents of this fork also, but only if it's not empty
 
        if org_repo.parent and org_repo.parent.scm_instance.revisions:
 
            add_other_repo(org_repo.parent)
 
            c.default_other_repo = org_repo.parent.repo_name
 

	
 
        c.default_other_repo_info = other_repos_info[c.default_other_repo]
 
        c.other_repos_info = json.dumps(other_repos_info)
 

	
 
        return render('/pullrequests/pullrequest.html')
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def create(self, repo_name):
 
        repo = RepoModel()._get_repo(repo_name)
 
        try:
 
            _form = PullRequestForm(repo.repo_id)().to_python(request.POST)
 
        except formencode.Invalid, errors:
 
            log.error(traceback.format_exc())
 
            if errors.error_dict.get('revisions'):
 
                msg = 'Revisions: %s' % errors.error_dict['revisions']
 
            elif errors.error_dict.get('pullrequest_title'):
 
                msg = _('Pull request requires a title with min. 3 chars')
 
            else:
 
                msg = _('Error creating pull request: %s') % errors.msg
 

	
 
            h.flash(msg, 'error')
 
            return redirect(url('pullrequest_home', repo_name=repo_name)) ## would rather just go back to form ...
 

	
 
        org_repo = _form['org_repo']
 
        org_ref = _form['org_ref'] # will end with merge_rev but have symbolic name
 
        other_repo = _form['other_repo']
 
        other_ref = 'rev:ancestor:%s' % _form['ancestor_rev'] # could be calculated from other_ref ...
 
        revisions = [x for x in reversed(_form['revisions'])]
 
        reviewers = _form['review_members']
 

	
 
        title = _form['pullrequest_title']
 
        if not title:
 
            title = '%s#%s to %s' % (org_repo, org_ref.split(':', 2)[1], other_repo)
 
        description = _form['pullrequest_desc']
 
        try:
 
            pull_request = PullRequestModel().create(
 
                self.rhodecode_user.user_id, org_repo, org_ref, other_repo,
 
                self.authuser.user_id, org_repo, org_ref, other_repo,
 
                other_ref, revisions, reviewers, title, description
 
            )
 
            Session().commit()
 
            h.flash(_('Successfully opened new pull request'),
 
                    category='success')
 
        except Exception:
 
            h.flash(_('Error occurred during sending pull request'),
 
                    category='error')
 
            log.error(traceback.format_exc())
 
            return redirect(url('pullrequest_home', repo_name=repo_name))
 

	
 
        return redirect(url('pullrequest_show', repo_name=other_repo,
 
                            pull_request_id=pull_request.pull_request_id))
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    @jsonify
 
    def update(self, repo_name, pull_request_id):
 
        pull_request = PullRequest.get_or_404(pull_request_id)
 
        if pull_request.is_closed():
 
            raise HTTPForbidden()
 
        #only owner or admin can update it
 
        owner = pull_request.author.user_id == c.rhodecode_user.user_id
 
        owner = pull_request.author.user_id == c.authuser.user_id
 
        repo_admin = h.HasRepoPermissionAny('repository.admin')(c.repo_name)
 
        if h.HasPermissionAny('hg.admin') or repo_admin or owner:
 
            reviewers_ids = map(int, filter(lambda v: v not in [None, ''],
 
                request.POST.get('reviewers_ids', '').split(',')))
 

	
 
            PullRequestModel().update_reviewers(pull_request_id, reviewers_ids)
 
            Session().commit()
 
            return True
 
        raise HTTPForbidden()
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    @jsonify
 
    def delete(self, repo_name, pull_request_id):
 
        pull_request = PullRequest.get_or_404(pull_request_id)
 
        #only owner can delete it !
 
        if pull_request.author.user_id == c.rhodecode_user.user_id:
 
        if pull_request.author.user_id == c.authuser.user_id:
 
            PullRequestModel().delete(pull_request)
 
            Session().commit()
 
            h.flash(_('Successfully deleted pull request'),
 
                    category='success')
 
            return redirect(url('my_account_pullrequests'))
 
        raise HTTPForbidden()
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def show(self, repo_name, pull_request_id):
 
        repo_model = RepoModel()
 
        c.users_array = repo_model.get_users_js()
 
        c.user_groups_array = repo_model.get_user_groups_js()
 
        c.pull_request = PullRequest.get_or_404(pull_request_id)
 
        c.allowed_to_change_status = self._get_is_allowed_change_status(c.pull_request)
 
        cc_model = ChangesetCommentsModel()
 
        cs_model = ChangesetStatusModel()
 
        _cs_statuses = cs_model.get_statuses(c.pull_request.org_repo,
 
                                            pull_request=c.pull_request,
 
                                            with_revisions=True)
 

	
 
        cs_statuses = defaultdict(list)
 
        for st in _cs_statuses:
 
            cs_statuses[st.author.username] += [st]
 

	
 
        c.pull_request_reviewers = []
 
        c.pull_request_pending_reviewers = []
 
        for o in c.pull_request.reviewers:
 
            st = cs_statuses.get(o.user.username, None)
 
            if st:
 
                sorter = lambda k: k.version
 
                st = [(x, list(y)[0])
 
                      for x, y in (groupby(sorted(st, key=sorter), sorter))]
 
            else:
 
                c.pull_request_pending_reviewers.append(o.user)
 
            c.pull_request_reviewers.append([o.user, st])
 

	
 
        # pull_requests repo_name we opened it against
 
        # ie. other_repo must match
 
        if repo_name != c.pull_request.other_repo.repo_name:
 
            raise HTTPNotFound
 

	
 
        # load compare data into template context
 
        enable_comments = not c.pull_request.is_closed()
 
        self._load_compare_data(c.pull_request, enable_comments=enable_comments)
 

	
 
        # inline comments
 
        c.inline_cnt = 0
 
        c.inline_comments = cc_model.get_inline_comments(
 
                                c.db_repo.repo_id,
 
                                pull_request=pull_request_id)
 
        # count inline comments
 
        for __, lines in c.inline_comments:
 
            for comments in lines.values():
 
                c.inline_cnt += len(comments)
 
        # comments
 
        c.comments = cc_model.get_comments(c.db_repo.repo_id,
 
                                           pull_request=pull_request_id)
 

	
 
        # (badly named) pull-request status calculation based on reviewer votes
 
        c.current_changeset_status = cs_model.calculate_status(
 
                                        c.pull_request_reviewers,
 
                                         )
 
        c.changeset_statuses = ChangesetStatus.STATUSES
 

	
 
        c.as_form = False
 
        c.ancestor = None # there is one - but right here we don't know which
 
        return render('/pullrequests/pullrequest_show.html')
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    @jsonify
 
    def comment(self, repo_name, pull_request_id):
 
        pull_request = PullRequest.get_or_404(pull_request_id)
 
        if pull_request.is_closed():
 
            raise HTTPForbidden()
 

	
 
        status = request.POST.get('changeset_status')
 
        change_status = request.POST.get('change_changeset_status')
 
        text = request.POST.get('text')
 
        close_pr = request.POST.get('save_close')
 

	
 
        allowed_to_change_status = self._get_is_allowed_change_status(pull_request)
 
        if status and change_status and allowed_to_change_status:
 
            _def = (_('Status change -> %s')
 
                            % ChangesetStatus.get_status_lbl(status))
 
            if close_pr:
 
                _def = _('Closing with') + ' ' + _def
 
            text = text or _def
 
        comm = ChangesetCommentsModel().create(
 
            text=text,
 
            repo=c.db_repo.repo_id,
 
            user=c.rhodecode_user.user_id,
 
            user=c.authuser.user_id,
 
            pull_request=pull_request_id,
 
            f_path=request.POST.get('f_path'),
 
            line_no=request.POST.get('line'),
 
            status_change=(ChangesetStatus.get_status_lbl(status)
 
                           if status and change_status
 
                           and allowed_to_change_status else None),
 
            closing_pr=close_pr
 
        )
 

	
 
        action_logger(self.rhodecode_user,
 
        action_logger(self.authuser,
 
                      'user_commented_pull_request:%s' % pull_request_id,
 
                      c.db_repo, self.ip_addr, self.sa)
 

	
 
        if allowed_to_change_status:
 
            # get status if set !
 
            if status and change_status:
 
                ChangesetStatusModel().set_status(
 
                    c.db_repo.repo_id,
 
                    status,
 
                    c.rhodecode_user.user_id,
 
                    c.authuser.user_id,
 
                    comm,
 
                    pull_request=pull_request_id
 
                )
 

	
 
            if close_pr:
 
                if status in ['rejected', 'approved']:
 
                    PullRequestModel().close_pull_request(pull_request_id)
 
                    action_logger(self.rhodecode_user,
 
                    action_logger(self.authuser,
 
                              'user_closed_pull_request:%s' % pull_request_id,
 
                              c.db_repo, self.ip_addr, self.sa)
 
                else:
 
                    h.flash(_('Closing pull request on other statuses than '
 
                              'rejected or approved forbidden'),
 
                            category='warning')
 

	
 
        Session().commit()
 

	
 
        if not request.environ.get('HTTP_X_PARTIAL_XHR'):
 
            return redirect(h.url('pullrequest_show', repo_name=repo_name,
 
                                  pull_request_id=pull_request_id))
 

	
 
        data = {
 
           'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
 
        }
 
        if comm:
 
            c.co = comm
 
            data.update(comm.get_dict())
 
            data.update({'rendered_text':
 
                         render('changeset/changeset_comment_block.html')})
 

	
 
        return data
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    @jsonify
 
    def delete_comment(self, repo_name, comment_id):
 
        co = ChangesetComment.get(comment_id)
 
        if co.pull_request.is_closed():
 
            #don't allow deleting comments on closed pull request
 
            raise HTTPForbidden()
 

	
 
        owner = co.author.user_id == c.rhodecode_user.user_id
 
        owner = co.author.user_id == c.authuser.user_id
 
        repo_admin = h.HasRepoPermissionAny('repository.admin')(c.repo_name)
 
        if h.HasPermissionAny('hg.admin') or repo_admin or owner:
 
            ChangesetCommentsModel().delete(comment=co)
 
            Session().commit()
 
            return True
 
        else:
 
            raise HTTPForbidden()
kallithea/controllers/summary.py
Show inline comments
 
@@ -91,98 +91,98 @@ class SummaryController(BaseRepoControll
 
        log.debug('Looking for README file')
 

	
 
        @cache_region('long_term')
 
        def _get_readme_from_cache(key, kind):
 
            readme_data = None
 
            readme_file = None
 
            try:
 
                # gets the landing revision! or tip if fails
 
                cs = db_repo.get_landing_changeset()
 
                if isinstance(cs, EmptyChangeset):
 
                    raise EmptyRepositoryError()
 
                renderer = MarkupRenderer()
 
                for f in README_FILES:
 
                    try:
 
                        readme = cs.get_node(f)
 
                        if not isinstance(readme, FileNode):
 
                            continue
 
                        readme_file = f
 
                        log.debug('Found README file `%s` rendering...' %
 
                                  readme_file)
 
                        readme_data = renderer.render(readme.content,
 
                                                      filename=f)
 
                        break
 
                    except NodeDoesNotExistError:
 
                        continue
 
            except ChangesetError:
 
                log.error(traceback.format_exc())
 
                pass
 
            except EmptyRepositoryError:
 
                pass
 
            except Exception:
 
                log.error(traceback.format_exc())
 

	
 
            return readme_data, readme_file
 

	
 
        kind = 'README'
 
        valid = CacheInvalidation.test_and_set_valid(repo_name, kind)
 
        if not valid:
 
            region_invalidate(_get_readme_from_cache, None, repo_name, kind)
 
        return _get_readme_from_cache(repo_name, kind)
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def index(self, repo_name):
 
        _load_changelog_summary()
 

	
 
        username = ''
 
        if self.rhodecode_user.username != User.DEFAULT_USER:
 
            username = safe_str(self.rhodecode_user.username)
 
        if self.authuser.username != User.DEFAULT_USER:
 
            username = safe_str(self.authuser.username)
 

	
 
        _def_clone_uri = _def_clone_uri_by_id = c.clone_uri_tmpl
 
        if '{repo}' in _def_clone_uri:
 
            _def_clone_uri_by_id = _def_clone_uri.replace('{repo}', '_{repoid}')
 
        elif '{repoid}' in _def_clone_uri:
 
            _def_clone_uri_by_id = _def_clone_uri.replace('_{repoid}', '{repo}')
 

	
 
        c.clone_repo_url = c.db_repo.clone_url(user=username,
 
                                                uri_tmpl=_def_clone_uri)
 
        c.clone_repo_url_id = c.db_repo.clone_url(user=username,
 
                                                uri_tmpl=_def_clone_uri_by_id)
 

	
 
        if c.db_repo.enable_statistics:
 
            c.show_stats = True
 
        else:
 
            c.show_stats = False
 

	
 
        stats = self.sa.query(Statistics)\
 
            .filter(Statistics.repository == c.db_repo)\
 
            .scalar()
 

	
 
        c.stats_percentage = 0
 

	
 
        if stats and stats.languages:
 
            c.no_data = False is c.db_repo.enable_statistics
 
            lang_stats_d = json.loads(stats.languages)
 

	
 
            lang_stats = ((x, {"count": y,
 
                               "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
 
                          for x, y in lang_stats_d.items())
 

	
 
            c.trending_languages = json.dumps(
 
                sorted(lang_stats, reverse=True, key=lambda k: k[1])[:10]
 
            )
 
        else:
 
            c.no_data = True
 
            c.trending_languages = json.dumps({})
 

	
 
        c.enable_downloads = c.db_repo.enable_downloads
 
        c.readme_data, c.readme_file = \
 
            self.__get_readme_data(c.db_repo)
 
        return render('summary/summary.html')
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    @jsonify
kallithea/lib/auth.py
Show inline comments
 
@@ -691,185 +691,185 @@ class AuthUser(object):
 
            except ObjectDeletedError:
 
                # since we use heavy caching sometimes it happens that we get
 
                # deleted objects here, we just skip them
 
                pass
 
        return _set or set(['0.0.0.0/0', '::/0'])
 

	
 

	
 
def set_available_permissions(config):
 
    """
 
    This function will propagate pylons globals with all available defined
 
    permission given in db. We don't want to check each time from db for new
 
    permissions since adding a new permission also requires application restart
 
    ie. to decorate new views with the newly created permission
 

	
 
    :param config: current pylons config instance
 

	
 
    """
 
    log.info('getting information about all available permissions')
 
    try:
 
        sa = meta.Session
 
        all_perms = sa.query(Permission).all()
 
        config['available_permissions'] = [x.permission_name for x in all_perms]
 
    except Exception:
 
        log.error(traceback.format_exc())
 
    finally:
 
        meta.Session.remove()
 

	
 

	
 
#==============================================================================
 
# CHECK DECORATORS
 
#==============================================================================
 
class LoginRequired(object):
 
    """
 
    Must be logged in to execute this function else
 
    redirect to login page
 

	
 
    :param api_access: if enabled this checks only for valid auth token
 
        and grants access based on valid token
 
    """
 

	
 
    def __init__(self, api_access=False):
 
        self.api_access = api_access
 

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

	
 
    def __wrapper(self, func, *fargs, **fkwargs):
 
        cls = fargs[0]
 
        user = cls.rhodecode_user
 
        user = cls.authuser
 
        loc = "%s:%s" % (cls.__class__.__name__, func.__name__)
 

	
 
        # check if our IP is allowed
 
        ip_access_valid = True
 
        if not user.ip_allowed:
 
            from kallithea.lib import helpers as h
 
            h.flash(h.literal(_('IP %s not allowed' % (user.ip_addr))),
 
                    category='warning')
 
            ip_access_valid = False
 

	
 
        # check if we used an APIKEY and it's a valid one
 
        # defined whitelist of controllers which API access will be enabled
 
        _api_key = request.GET.get('api_key', '')
 
        api_access_valid = allowed_api_access(loc, api_key=_api_key)
 

	
 
        # explicit controller is enabled or API is in our whitelist
 
        if self.api_access or api_access_valid:
 
            log.debug('Checking API KEY access for %s' % cls)
 
            if _api_key and _api_key in user.api_keys:
 
                api_access_valid = True
 
                log.debug('API KEY ****%s is VALID' % _api_key[-4:])
 
            else:
 
                api_access_valid = False
 
                if not _api_key:
 
                    log.debug("API KEY *NOT* present in request")
 
                else:
 
                    log.warn("API KEY ****%s *NOT* valid" % _api_key[-4:])
 

	
 
        log.debug('Checking if %s is authenticated @ %s' % (user.username, loc))
 
        reason = 'RegularAuth' if user.is_authenticated else 'APIAuth'
 

	
 
        if ip_access_valid and (user.is_authenticated or api_access_valid):
 
            log.info('user %s authenticating with:%s IS authenticated on func %s '
 
                     % (user, reason, loc)
 
            )
 
            return func(*fargs, **fkwargs)
 
        else:
 
            log.warn('user %s authenticating with:%s NOT authenticated on func: %s: '
 
                     'IP_ACCESS:%s API_ACCESS:%s'
 
                     % (user, reason, loc, ip_access_valid, api_access_valid)
 
            )
 
            p = url.current()
 

	
 
            log.debug('redirecting to login page with %s' % p)
 
            return redirect(url('login_home', came_from=p))
 

	
 

	
 
class NotAnonymous(object):
 
    """
 
    Must be logged in to execute this function else
 
    redirect to login page"""
 

	
 
    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 = cls.authuser
 

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

	
 
        anonymous = self.user.username == User.DEFAULT_USER
 

	
 
        if anonymous:
 
            p = url.current()
 

	
 
            import kallithea.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):
 
        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 = cls.authuser
 
        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.debug('Permission denied for %s %s' % (cls, self.user))
 
            anonymous = self.user.username == User.DEFAULT_USER
 

	
 
            if anonymous:
 
                p = url.current()
 

	
 
                import kallithea.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
 
    """
 

	
kallithea/lib/base.py
Show inline comments
 
@@ -269,148 +269,148 @@ class BaseVCSController(object):
 
    def __call__(self, environ, start_response):
 
        start = time.time()
 
        try:
 
            return self._handle_request(environ, start_response)
 
        finally:
 
            log = logging.getLogger('kallithea.' + self.__class__.__name__)
 
            log.debug('Request time: %.3fs' % (time.time() - start))
 
            meta.Session.remove()
 

	
 

	
 
class BaseController(WSGIController):
 

	
 
    def __before__(self):
 
        """
 
        __before__ is called before controller methods and after __call__
 
        """
 
        c.rhodecode_version = __version__
 
        rc_config = RhodeCodeSetting.get_app_settings()
 

	
 
        # Visual options
 
        c.visual = AttributeDict({})
 

	
 
        ## DB stored
 
        c.visual.show_public_icon = str2bool(rc_config.get('rhodecode_show_public_icon'))
 
        c.visual.show_private_icon = str2bool(rc_config.get('rhodecode_show_private_icon'))
 
        c.visual.stylify_metatags = str2bool(rc_config.get('rhodecode_stylify_metatags'))
 
        c.visual.dashboard_items = safe_int(rc_config.get('rhodecode_dashboard_items', 100))
 
        c.visual.admin_grid_items = safe_int(rc_config.get('rhodecode_admin_grid_items', 100))
 
        c.visual.repository_fields = str2bool(rc_config.get('rhodecode_repository_fields'))
 
        c.visual.show_version = str2bool(rc_config.get('rhodecode_show_version'))
 
        c.visual.use_gravatar = str2bool(rc_config.get('rhodecode_use_gravatar'))
 
        c.visual.gravatar_url = rc_config.get('rhodecode_gravatar_url')
 

	
 
        c.ga_code = rc_config.get('rhodecode_ga_code')
 
        c.rhodecode_name = rc_config.get('rhodecode_title')
 
        c.clone_uri_tmpl = rc_config.get('rhodecode_clone_uri_tmpl')
 

	
 
        ## INI stored
 
        c.visual.allow_repo_location_change = str2bool(config.get('allow_repo_location_change', True))
 
        c.visual.allow_custom_hooks_settings = str2bool(config.get('allow_custom_hooks_settings', True))
 

	
 
        c.rhodecode_instanceid = config.get('instance_id')
 
        c.issues_url = config.get('bugtracker', url('issues_url'))
 
        # END CONFIG VARS
 

	
 
        c.repo_name = get_repo_slug(request)  # can be empty
 
        c.backends = BACKENDS.keys()
 
        c.unread_notifications = NotificationModel()\
 
                        .get_unread_cnt_for_user(c.rhodecode_user.user_id)
 
                        .get_unread_cnt_for_user(c.authuser.user_id)
 

	
 
        self.cut_off_limit = safe_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']
 
        try:
 
            self.ip_addr = _get_ip_addr(environ)
 
            # make sure that we update permissions each time we call controller
 
            api_key = request.GET.get('api_key')
 

	
 
            if api_key:
 
                # when using API_KEY we are sure user exists.
 
                auth_user = AuthUser(api_key=api_key, ip_addr=self.ip_addr)
 
                authenticated = False
 
            else:
 
                cookie_store = CookieStoreWrapper(session.get('rhodecode_user'))
 
                cookie_store = CookieStoreWrapper(session.get('authuser'))
 
                try:
 
                    auth_user = AuthUser(user_id=cookie_store.get('user_id', None),
 
                                         ip_addr=self.ip_addr)
 
                except UserCreationError, e:
 
                    from kallithea.lib import helpers as h
 
                    h.flash(e, 'error')
 
                    # container auth or other auth functions that create users on
 
                    # the fly can throw this exception signaling that there's issue
 
                    # with user creation, explanation should be provided in
 
                    # Exception itself
 
                    auth_user = AuthUser(ip_addr=self.ip_addr)
 

	
 
                authenticated = cookie_store.get('is_authenticated')
 

	
 
            if not auth_user.is_authenticated and auth_user.user_id is not None:
 
                # user is not authenticated and not empty
 
                auth_user.set_authenticated(authenticated)
 
            request.user = auth_user
 
            #set globals for auth user
 
            self.rhodecode_user = c.rhodecode_user = auth_user
 
            self.authuser = c.authuser = auth_user
 
            log.info('IP: %s User: %s accessed %s' % (
 
               self.ip_addr, auth_user, safe_unicode(_get_access_path(environ)))
 
            )
 
            return WSGIController.__call__(self, environ, start_response)
 
        finally:
 
            meta.Session.remove()
 

	
 

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

	
 
    c.db_repo_scm_instance: instance of scm repository
 
    c.db_repo: instance of db
 
    c.repository_followers: number of followers
 
    c.repository_forks: number of forks
 
    c.repository_following: weather the current user is following the current repo
 
    """
 

	
 
    def __before__(self):
 
        super(BaseRepoController, self).__before__()
 
        if c.repo_name:  # extracted from routes
 
            _dbr = Repository.get_by_repo_name(c.repo_name)
 
            if not _dbr:
 
                return
 

	
 
            log.debug('Found repository in database %s with state `%s`'
 
                      % (safe_unicode(_dbr), safe_unicode(_dbr.repo_state)))
 
            route = getattr(request.environ.get('routes.route'), 'name', '')
 

	
 
            # allow to delete repos that are somehow damages in filesystem
 
            if route in ['delete_repo']:
 
                return
 

	
 
            if _dbr.repo_state in [Repository.STATE_PENDING]:
 
                if route in ['repo_creating_home']:
 
                    return
 
                check_url = url('repo_creating_home', repo_name=c.repo_name)
 
                return redirect(check_url)
 

	
 
            dbr = c.db_repo = _dbr
 
            c.db_repo_scm_instance = c.db_repo.scm_instance
 
            if c.db_repo_scm_instance 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'))
 

	
 
            # update last change according to VCS data
 
            dbr.update_changeset_cache(dbr.get_changeset())
 

	
 
            # some globals counter for menu
 
            c.repository_followers = self.scm_model.get_followers(dbr)
 
            c.repository_forks = self.scm_model.get_forks(dbr)
 
            c.repository_pull_requests = self.scm_model.get_pull_requests(dbr)
 
            c.repository_following = self.scm_model.is_following_repo(
 
                                    c.repo_name, self.rhodecode_user.user_id)
 
                                    c.repo_name, self.authuser.user_id)
kallithea/lib/utils.py
Show inline comments
 
@@ -11,97 +11,97 @@
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
"""
 
kallithea.lib.utils
 
~~~~~~~~~~~~~~~~~~~
 

	
 
Utilities library for RhodeCode
 

	
 
:created_on: Apr 18, 2010
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH.
 
:license: GPLv3, see LICENSE for more details.
 
"""
 

	
 
import os
 
import re
 
import logging
 
import datetime
 
import traceback
 
import paste
 
import beaker
 
import tarfile
 
import shutil
 
import decorator
 
import warnings
 
from os.path import abspath
 
from os.path import dirname as dn, join as jn
 

	
 
from paste.script.command import Command, BadCommand
 

	
 
from webhelpers.text import collapse, remove_formatting, strip_tags
 
from beaker.cache import _cache_decorate
 

	
 
from kallithea.lib.vcs import get_backend
 
from kallithea.lib.vcs.backends.base import BaseChangeset
 
from kallithea.lib.vcs.utils.lazy import LazyProperty
 
from kallithea.lib.vcs.utils.hgcompat import ui, config
 
from kallithea.lib.vcs.utils.helpers import get_scm
 
from kallithea.lib.vcs.exceptions import VCSError
 

	
 
from kallithea.lib.caching_query import FromCache
 

	
 
from kallithea.model import meta
 
from kallithea.model.db import Repository, User, RhodeCodeUi, \
 
    UserLog, RepoGroup, RhodeCodeSetting, CacheInvalidation, UserGroup
 
from kallithea.model.meta import Session
 
from kallithea.model.repo_group import RepoGroupModel
 
from kallithea.lib.utils2 import safe_str, safe_unicode, get_current_rhodecode_user
 
from kallithea.lib.utils2 import safe_str, safe_unicode, get_current_authuser
 
from kallithea.lib.vcs.utils.fakemod import create_module
 
from kallithea.model.user_group import UserGroupModel
 

	
 
log = logging.getLogger(__name__)
 

	
 
REMOVED_REPO_PAT = re.compile(r'rm__\d{8}_\d{6}_\d{6}__.*')
 

	
 

	
 
def recursive_replace(str_, replace=' '):
 
    """
 
    Recursive replace of given sign to just one instance
 

	
 
    :param str_: given string
 
    :param replace: char to find and replace multiple instances
 

	
 
    Examples::
 
    >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
 
    'Mighty-Mighty-Bo-sstones'
 
    """
 

	
 
    if str_.find(replace * 2) == -1:
 
        return str_
 
    else:
 
        str_ = str_.replace(replace * 2, replace)
 
        return recursive_replace(str_, replace)
 

	
 

	
 
def repo_name_slug(value):
 
    """
 
    Return slug of name of repository
 
    This function is called on each creation/modification
 
    of repository to prevent bad names in repo
 
    """
 

	
 
    slug = remove_formatting(value)
 
    slug = strip_tags(slug)
 

	
 
    for c in """`?=[]\;'"<>,/~!@#$%^&*()+{}|: """:
 
        slug = slug.replace(c, '-')
 
    slug = recursive_replace(slug, '-')
 
    slug = collapse(slug, '-')
 
    return slug
 

	
 

	
 
#==============================================================================
 
# PERM DECORATOR HELPERS FOR EXTRACTING NAMES FOR PERM CHECKS
 
#==============================================================================
 
def get_repo_slug(request):
 
@@ -133,97 +133,97 @@ def get_user_group_slug(request):
 

	
 

	
 
def _extract_id_from_repo_name(repo_name):
 
    if repo_name.startswith('/'):
 
        repo_name = repo_name.lstrip('/')
 
    by_id_match = re.match(r'^_(\d{1,})', repo_name)
 
    if by_id_match:
 
        return by_id_match.groups()[0]
 

	
 

	
 
def get_repo_by_id(repo_name):
 
    """
 
    Extracts repo_name by id from special urls. Example url is _11/repo_name
 

	
 
    :param repo_name:
 
    :return: repo_name if matched else None
 
    """
 
    try:
 
        _repo_id = _extract_id_from_repo_name(repo_name)
 
        if _repo_id:
 
            from kallithea.model.db import Repository
 
            return Repository.get(_repo_id).repo_name
 
    except Exception:
 
        log.debug('Failed to extract repo_name from URL %s' % (
 
                  traceback.format_exc()))
 
        return
 

	
 

	
 
def action_logger(user, action, repo, ipaddr='', sa=None, commit=False):
 
    """
 
    Action logger for various actions made by users
 

	
 
    :param user: user that made this action, can be a unique username string or
 
        object containing user_id attribute
 
    :param action: action to log, should be on of predefined unique actions for
 
        easy translations
 
    :param repo: string name of repository or object containing repo_id,
 
        that action was made on
 
    :param ipaddr: optional ip address from what the action was made
 
    :param sa: optional sqlalchemy session
 

	
 
    """
 

	
 
    if not sa:
 
        sa = meta.Session()
 
    # if we don't get explicit IP address try to get one from registered user
 
    # in tmpl context var
 
    if not ipaddr:
 
        ipaddr = getattr(get_current_rhodecode_user(), 'ip_addr', '')
 
        ipaddr = getattr(get_current_authuser(), 'ip_addr', '')
 

	
 
    try:
 
        if getattr(user, 'user_id', None):
 
            user_obj = User.get(user.user_id)
 
        elif isinstance(user, basestring):
 
            user_obj = User.get_by_username(user)
 
        else:
 
            raise Exception('You have to provide a user object or a username')
 

	
 
        if getattr(repo, 'repo_id', None):
 
            repo_obj = Repository.get(repo.repo_id)
 
            repo_name = repo_obj.repo_name
 
        elif isinstance(repo, basestring):
 
            repo_name = repo.lstrip('/')
 
            repo_obj = Repository.get_by_repo_name(repo_name)
 
        else:
 
            repo_obj = None
 
            repo_name = ''
 

	
 
        user_log = UserLog()
 
        user_log.user_id = user_obj.user_id
 
        user_log.username = user_obj.username
 
        user_log.action = safe_unicode(action)
 

	
 
        user_log.repository = repo_obj
 
        user_log.repository_name = repo_name
 

	
 
        user_log.action_date = datetime.datetime.now()
 
        user_log.user_ip = ipaddr
 
        sa.add(user_log)
 

	
 
        log.info('Logging action:%s on %s by user:%s ip:%s' %
 
                 (action, safe_unicode(repo), user_obj, ipaddr))
 
        if commit:
 
            sa.commit()
 
    except Exception:
 
        log.error(traceback.format_exc())
 
        raise
 

	
 

	
 
def get_filesystem_repos(path, recursive=False, skip_removed_repos=True):
 
    """
 
    Scans given path for repos and return (name,(type,path)) tuple
 

	
 
    :param path: path to scan for repositories
 
    :param recursive: recursive search and return names with subdirs in front
 
    """
 

	
kallithea/lib/utils2.py
Show inline comments
 
@@ -626,104 +626,104 @@ def _extract_extras(env=None):
 
                  'action', 'ip']:
 
            rc_extras[k]
 
    except KeyError, e:
 
        raise Exception('Missing key %s in os.environ %s' % (e, rc_extras))
 

	
 
    return AttributeDict(rc_extras)
 

	
 

	
 
def _set_extras(extras):
 
    os.environ['RC_SCM_DATA'] = json.dumps(extras)
 

	
 

	
 
def unique_id(hexlen=32):
 
    alphabet = "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjklmnpqrstuvwxyz"
 
    return suuid(truncate_to=hexlen, alphabet=alphabet)
 

	
 

	
 
def suuid(url=None, truncate_to=22, alphabet=None):
 
    """
 
    Generate and return a short URL safe UUID.
 

	
 
    If the url parameter is provided, set the namespace to the provided
 
    URL and generate a UUID.
 

	
 
    :param url to get the uuid for
 
    :truncate_to: truncate the basic 22 UUID to shorter version
 

	
 
    The IDs won't be universally unique any longer, but the probability of
 
    a collision will still be very low.
 
    """
 
    # Define our alphabet.
 
    _ALPHABET = alphabet or "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"
 

	
 
    # If no URL is given, generate a random UUID.
 
    if url is None:
 
        unique_id = uuid.uuid4().int
 
    else:
 
        unique_id = uuid.uuid3(uuid.NAMESPACE_URL, url).int
 

	
 
    alphabet_length = len(_ALPHABET)
 
    output = []
 
    while unique_id > 0:
 
        digit = unique_id % alphabet_length
 
        output.append(_ALPHABET[digit])
 
        unique_id = int(unique_id / alphabet_length)
 
    return "".join(output)[:truncate_to]
 

	
 

	
 
def get_current_rhodecode_user():
 
def get_current_authuser():
 
    """
 
    Gets rhodecode user from threadlocal tmpl_context variable if it's
 
    defined, else returns None.
 
    """
 
    from pylons import tmpl_context
 
    if hasattr(tmpl_context, 'rhodecode_user'):
 
        return tmpl_context.rhodecode_user
 
    if hasattr(tmpl_context, 'authuser'):
 
        return tmpl_context.authuser
 

	
 
    return None
 

	
 

	
 
class OptionalAttr(object):
 
    """
 
    Special Optional Option that defines other attribute. Example::
 

	
 
        def test(apiuser, userid=Optional(OAttr('apiuser')):
 
            user = Optional.extract(userid)
 
            # calls
 

	
 
    """
 

	
 
    def __init__(self, attr_name):
 
        self.attr_name = attr_name
 

	
 
    def __repr__(self):
 
        return '<OptionalAttr:%s>' % self.attr_name
 

	
 
    def __call__(self):
 
        return self
 

	
 
#alias
 
OAttr = OptionalAttr
 

	
 

	
 
class Optional(object):
 
    """
 
    Defines an optional parameter::
 

	
 
        param = param.getval() if isinstance(param, Optional) else param
 
        param = param() if isinstance(param, Optional) else param
 

	
 
    is equivalent of::
 

	
 
        param = Optional.extract(param)
 

	
 
    """
 

	
 
    def __init__(self, type_):
 
        self.type_ = type_
 

	
 
    def __repr__(self):
 
        return '<Optional:%s>' % self.type_.__repr__()
 

	
 
    def __call__(self):
 
        return self.getval()
kallithea/model/repo.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
# This program is free software: you can redistribute it and/or modify
 
# it under the terms of the GNU General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# 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, see <http://www.gnu.org/licenses/>.
 
"""
 
kallithea.model.repo
 
~~~~~~~~~~~~~~~~~~~~
 

	
 
Repository model for rhodecode
 

	
 
:created_on: Jun 5, 2010
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH.
 
:license: GPLv3, see LICENSE for more details.
 

	
 
"""
 

	
 
from __future__ import with_statement
 
import os
 
import shutil
 
import logging
 
import traceback
 
from datetime import datetime
 
from kallithea.lib.utils import make_ui
 

	
 
from kallithea.lib.vcs.backends import get_backend
 
from kallithea.lib.compat import json
 
from kallithea.lib.utils2 import LazyProperty, safe_str, safe_unicode, \
 
    remove_prefix, obfuscate_url_pw, get_current_rhodecode_user
 
    remove_prefix, obfuscate_url_pw, get_current_authuser
 
from kallithea.lib.caching_query import FromCache
 
from kallithea.lib.hooks import log_create_repository, log_delete_repository
 

	
 
from kallithea.model import BaseModel
 
from kallithea.model.db import Repository, UserRepoToPerm, UserGroupRepoToPerm, \
 
    UserRepoGroupToPerm, UserGroupRepoGroupToPerm, User, Permission, \
 
    Statistics, UserGroup, RhodeCodeUi, RepoGroup, \
 
    RhodeCodeSetting, RepositoryField
 

	
 
from kallithea.lib import helpers as h
 
from kallithea.lib.auth import HasRepoPermissionAny, HasUserGroupPermissionAny
 
from kallithea.lib.exceptions import AttachedForksError
 
from kallithea.model.scm import UserGroupList
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class RepoModel(BaseModel):
 

	
 
    cls = Repository
 
    URL_SEPARATOR = Repository.url_sep()
 

	
 
    def _get_user_group(self, users_group):
 
        return self._get_instance(UserGroup, users_group,
 
                                  callback=UserGroup.get_by_group_name)
 

	
 
    def _get_repo_group(self, repo_group):
 
        return self._get_instance(RepoGroup, repo_group,
 
                                  callback=RepoGroup.get_by_group_name)
 

	
 
    def _create_default_perms(self, repository, private):
 
        # create default permission
 
        default = 'repository.read'
 
        def_user = User.get_default_user()
 
        for p in def_user.user_perms:
 
            if p.permission.permission_name.startswith('repository.'):
 
                default = p.permission.permission_name
 
                break
 

	
 
        default_perm = 'repository.none' if private else default
 

	
 
        repo_to_perm = UserRepoToPerm()
 
        repo_to_perm.permission = Permission.get_by_key(default_perm)
 

	
 
        repo_to_perm.repository = repository
 
        repo_to_perm.user_id = def_user.user_id
 

	
 
        return repo_to_perm
 
@@ -492,97 +492,97 @@ class RepoModel(BaseModel):
 
                    repo=repo, user=member, perm=perm
 
                )
 
            else:
 
                #check if we have permissions to alter this usergroup
 
                req_perms = (
 
                    'usergroup.read', 'usergroup.write', 'usergroup.admin')
 
                if not check_perms or HasUserGroupPermissionAny(*req_perms)(
 
                        member):
 
                    self.grant_user_group_permission(
 
                        repo=repo, group_name=member, perm=perm
 
                    )
 
            # set new permissions
 
        for member, perm, member_type in perms_new:
 
            if member_type == 'user':
 
                self.grant_user_permission(
 
                    repo=repo, user=member, perm=perm
 
                )
 
            else:
 
                #check if we have permissions to alter this usergroup
 
                req_perms = (
 
                    'usergroup.read', 'usergroup.write', 'usergroup.admin')
 
                if not check_perms or HasUserGroupPermissionAny(*req_perms)(
 
                        member):
 
                    self.grant_user_group_permission(
 
                        repo=repo, group_name=member, perm=perm
 
                    )
 

	
 
    def create_fork(self, form_data, cur_user):
 
        """
 
        Simple wrapper into executing celery task for fork creation
 

	
 
        :param form_data:
 
        :param cur_user:
 
        """
 
        from kallithea.lib.celerylib import tasks, run_task
 
        return run_task(tasks.create_repo_fork, form_data, cur_user)
 

	
 
    def delete(self, repo, forks=None, fs_remove=True, cur_user=None):
 
        """
 
        Delete given repository, forks parameter defines what do do with
 
        attached forks. Throws AttachedForksError if deleted repo has attached
 
        forks
 

	
 
        :param repo:
 
        :param forks: str 'delete' or 'detach'
 
        :param fs_remove: remove(archive) repo from filesystem
 
        """
 
        if not cur_user:
 
            cur_user = getattr(get_current_rhodecode_user(), 'username', None)
 
            cur_user = getattr(get_current_authuser(), 'username', None)
 
        repo = self._get_repo(repo)
 
        if repo:
 
            if forks == 'detach':
 
                for r in repo.forks:
 
                    r.fork = None
 
                    self.sa.add(r)
 
            elif forks == 'delete':
 
                for r in repo.forks:
 
                    self.delete(r, forks='delete')
 
            elif [f for f in repo.forks]:
 
                raise AttachedForksError()
 

	
 
            old_repo_dict = repo.get_dict()
 
            owner = repo.user
 
            try:
 
                self.sa.delete(repo)
 
                if fs_remove:
 
                    self._delete_filesystem_repo(repo)
 
                else:
 
                    log.debug('skipping removal from filesystem')
 
                log_delete_repository(old_repo_dict,
 
                                      deleted_by=cur_user)
 
            except Exception:
 
                log.error(traceback.format_exc())
 
                raise
 

	
 
    def grant_user_permission(self, repo, user, perm):
 
        """
 
        Grant permission for user on given repository, or update existing one
 
        if found
 

	
 
        :param repo: Instance of Repository, repository_id, or repository name
 
        :param user: Instance of User, user_id or username
 
        :param perm: Instance of Permission, or permission_name
 
        """
 
        user = self._get_user(user)
 
        repo = self._get_repo(repo)
 
        permission = self._get_perm(perm)
 

	
 
        # check if we have that permission already
 
        obj = self.sa.query(UserRepoToPerm) \
 
            .filter(UserRepoToPerm.user == user) \
 
            .filter(UserRepoToPerm.repository == repo) \
 
            .scalar()
 
        if obj is None:
 
            # create new !
 
            obj = UserRepoToPerm()
 
        obj.repository = repo
kallithea/model/user.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
# This program is free software: you can redistribute it and/or modify
 
# it under the terms of the GNU General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# 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, see <http://www.gnu.org/licenses/>.
 
"""
 
kallithea.model.user
 
~~~~~~~~~~~~~~~~~~~~
 

	
 
users model for RhodeCode
 

	
 
:created_on: Apr 9, 2010
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH.
 
:license: GPLv3, see LICENSE for more details.
 
"""
 

	
 

	
 
import logging
 
import traceback
 
from pylons import url
 
from pylons.i18n.translation import _
 

	
 
from sqlalchemy.exc import DatabaseError
 

	
 

	
 
from kallithea.lib.utils2 import safe_unicode, generate_api_key, get_current_rhodecode_user
 
from kallithea.lib.utils2 import safe_unicode, generate_api_key, get_current_authuser
 
from kallithea.lib.caching_query import FromCache
 
from kallithea.model import BaseModel
 
from kallithea.model.db import User, UserToPerm, Notification, \
 
    UserEmailMap, UserIpMap
 
from kallithea.lib.exceptions import DefaultUserException, \
 
    UserOwnsReposException
 
from kallithea.model.meta import Session
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class UserModel(BaseModel):
 
    cls = User
 

	
 
    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_user(self, user):
 
        return self._get_user(user)
 

	
 
    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_email(self, email, cache=False, case_insensitive=False):
 
        return User.get_by_email(email, case_insensitive, cache)
 

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

	
 
    def create(self, form_data, cur_user=None):
 
        if not cur_user:
 
            cur_user = getattr(get_current_rhodecode_user(), 'username', None)
 
            cur_user = getattr(get_current_authuser(), 'username', None)
 

	
 
        from kallithea.lib.hooks import log_create_user, check_allowed_create_user
 
        _fd = form_data
 
        user_data = {
 
            'username': _fd['username'], 'password': _fd['password'],
 
            'email': _fd['email'], 'firstname': _fd['firstname'], 'lastname': _fd['lastname'],
 
            'active': _fd['active'], 'admin': False
 
        }
 
        # raises UserCreationError if it's not allowed
 
        check_allowed_create_user(user_data, cur_user)
 
        from kallithea.lib.auth import get_crypt_password
 
        try:
 
            new_user = User()
 
            for k, v in form_data.items():
 
                if k == 'password':
 
                    v = get_crypt_password(v)
 
                if k == 'firstname':
 
                    k = 'name'
 
                setattr(new_user, k, v)
 

	
 
            new_user.api_key = generate_api_key(form_data['username'])
 
            self.sa.add(new_user)
 

	
 
            log_create_user(new_user.get_dict(), cur_user)
 
            return new_user
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def create_or_update(self, username, password, email, firstname='',
 
                         lastname='', active=True, admin=False,
 
                         extern_type=None, extern_name=None, cur_user=None):
 
        """
 
        Creates a new instance if not found, or updates current one
 

	
 
        :param username:
 
        :param password:
 
        :param email:
 
        :param active:
 
        :param firstname:
 
        :param lastname:
 
        :param active:
 
        :param admin:
 
        :param extern_name:
 
        :param extern_type:
 
        :param cur_user:
 
        """
 
        if not cur_user:
 
            cur_user = getattr(get_current_rhodecode_user(), 'username', None)
 
            cur_user = getattr(get_current_authuser(), 'username', None)
 

	
 
        from kallithea.lib.auth import get_crypt_password, check_password
 
        from kallithea.lib.hooks import log_create_user, check_allowed_create_user
 
        user_data = {
 
            'username': username, 'password': password,
 
            'email': email, 'firstname': firstname, 'lastname': lastname,
 
            'active': active, 'admin': admin
 
        }
 
        # raises UserCreationError if it's not allowed
 
        check_allowed_create_user(user_data, cur_user)
 

	
 
        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)
 
            new_user = User()
 
            edit = False
 
        else:
 
            log.debug('updating user %s' % username)
 
            new_user = user
 
            edit = True
 

	
 
        try:
 
            new_user.username = username
 
            new_user.admin = admin
 
            new_user.email = email
 
            new_user.active = active
 
            new_user.extern_name = safe_unicode(extern_name) if extern_name else None
 
            new_user.extern_type = safe_unicode(extern_type) if extern_type else None
 
            new_user.name = firstname
 
            new_user.lastname = lastname
 

	
 
            if not edit:
 
                new_user.api_key = generate_api_key(username)
 

	
 
            # set password only if creating an user or password is changed
 
            password_change = new_user.password and not check_password(password,
 
                                                            new_user.password)
 
            if not edit or password_change:
 
                reason = 'new password' if edit else 'new user'
 
                log.debug('Updating password reason=>%s' % (reason,))
 
                new_user.password = get_crypt_password(password) if password else None
 

	
 
            self.sa.add(new_user)
 

	
 
            if not edit:
 
                log_create_user(new_user.get_dict(), cur_user)
 
            return new_user
 
@@ -214,97 +214,97 @@ class UserModel(BaseModel):
 
    def update(self, user_id, form_data, skip_attrs=[]):
 
        from kallithea.lib.auth import get_crypt_password
 
        try:
 
            user = self.get(user_id, cache=False)
 
            if user.username == User.DEFAULT_USER:
 
                raise DefaultUserException(
 
                                _("You can't Edit this user since it's "
 
                                  "crucial for entire application"))
 

	
 
            for k, v in form_data.items():
 
                if k in skip_attrs:
 
                    continue
 
                if k == 'new_password' and v:
 
                    user.password = get_crypt_password(v)
 
                else:
 
                    # old legacy thing orm models store firstname as name,
 
                    # need proper refactor to username
 
                    if k == 'firstname':
 
                        k = 'name'
 
                    setattr(user, k, v)
 
            self.sa.add(user)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def update_user(self, user, **kwargs):
 
        from kallithea.lib.auth import get_crypt_password
 
        try:
 
            user = self._get_user(user)
 
            if user.username == User.DEFAULT_USER:
 
                raise DefaultUserException(
 
                    _("You can't Edit this user since it's"
 
                      " crucial for entire application")
 
                )
 

	
 
            for k, v in kwargs.items():
 
                if k == 'password' and v:
 
                    v = get_crypt_password(v)
 

	
 
                setattr(user, k, v)
 
            self.sa.add(user)
 
            return user
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def delete(self, user, cur_user=None):
 
        if not cur_user:
 
            cur_user = getattr(get_current_rhodecode_user(), 'username', None)
 
            cur_user = getattr(get_current_authuser(), 'username', None)
 
        user = self._get_user(user)
 

	
 
        try:
 
            if user.username == User.DEFAULT_USER:
 
                raise DefaultUserException(
 
                    _(u"You can't remove this user since it's"
 
                      " crucial for entire application")
 
                )
 
            if user.repositories:
 
                repos = [x.repo_name for x in user.repositories]
 
                raise UserOwnsReposException(
 
                    _(u'user "%s" still owns %s repositories and cannot be '
 
                      'removed. Switch owners or remove those repositories. %s')
 
                    % (user.username, len(repos), ', '.join(repos))
 
                )
 
            self.sa.delete(user)
 

	
 
            from kallithea.lib.hooks import log_delete_user
 
            log_delete_user(user.get_dict(), cur_user)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def reset_password_link(self, data):
 
        from kallithea.lib.celerylib import tasks, run_task
 
        from kallithea.model.notification import EmailNotificationModel
 
        user_email = data['email']
 
        try:
 
            user = User.get_by_email(user_email)
 
            if user:
 
                log.debug('password reset user found %s' % user)
 
                link = url('reset_password_confirmation', key=user.api_key,
 
                           qualified=True)
 
                reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET
 
                body = EmailNotificationModel().get_email_tmpl(reg_type,
 
                                                    **{'user': user.short_contact,
 
                                                       'reset_url': link})
 
                log.debug('sending email')
 
                run_task(tasks.send_email, user_email,
 
                         _("Password reset link"), body, body)
 
                log.info('send new password mail to %s' % user_email)
 
            else:
 
                log.debug("password reset email %s not found" % user_email)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            return False
 

	
 
        return True
kallithea/templates/admin/gists/edit.html
Show inline comments
 
@@ -6,97 +6,97 @@
 
    %if c.rhodecode_name:
 
        &middot; ${c.rhodecode_name}
 
    %endif
 
</%def>
 

	
 
<%def name="js_extra()">
 
<script type="text/javascript" src="${h.url('/js/codemirror.js')}"></script>
 
<script type="text/javascript" src="${h.url('/js/codemirror_loadmode.js')}"></script>
 
<script type="text/javascript" src="${h.url('/js/mode/meta.js')}"></script>
 
<script type="text/javascript" src="${h.url('/js/mode/meta_ext.js')}"></script>
 
</%def>
 
<%def name="css_extra()">
 
<link rel="stylesheet" type="text/css" href="${h.url('/css/codemirror.css')}"/>
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${_('Edit Gist')} &middot; ${c.gist.gist_access_id}
 
</%def>
 

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

	
 
<%def name="main()">
 
<div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
    </div>
 

	
 
    <div class="table">
 
        <div id="edit_error" style="display: none" class="flash_msg">
 
            <div class="alert alert-dismissable alert-warning">
 
              <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
 
              ${h.literal(_('Gist was update since you started editing. Copy your changes and click %(here)s to reload new version.')
 
                             % {'here': h.link_to('here',h.url('edit_gist', gist_id=c.gist.gist_access_id))})}
 
            </div>
 
            <script>
 
            if (typeof jQuery != 'undefined') {
 
                $(".alert").alert();
 
            }
 
            </script>
 
        </div>
 

	
 
        <div id="files_data">
 
          ${h.form(h.url('edit_gist', gist_id=c.gist.gist_access_id), method='post', id='eform')}
 
            <div>
 
                <div class="gravatar">
 
                   <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(c.rhodecode_user.full_contact),32)}"/>
 
                   <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(c.authuser.full_contact),32)}"/>
 
                </div>
 
                <input type="hidden" value="${c.file_changeset.raw_id}" name="parent_hash">
 
                <textarea style="resize:vertical; width:400px;border: 1px solid #ccc;border-radius: 3px;"
 
                          id="description" name="description"
 
                          placeholder="${_('Gist description ...')}">${c.gist.gist_description}</textarea>
 
                <div style="padding:0px 0px 0px 42px">
 
                    <label for='lifetime'>${_('Gist lifetime')}</label>
 
                    ${h.select('lifetime', '0', c.lifetime_options)}
 
                    <span class="" style="color: #AAA">
 
                     %if c.gist.gist_expires == -1:
 
                      ${_('Expires')}: ${_('never')}
 
                     %else:
 
                      ${_('Expires')}: ${h.age(h.time_to_datetime(c.gist.gist_expires))}
 
                     %endif
 
                   </span>
 
                </div>
 
            </div>
 

	
 
            % for cnt, file in enumerate(c.files):
 
                <div id="body" class="codeblock" style="margin-bottom: 4px">
 
                    <div style="padding: 10px 10px 10px 26px;color:#666666">
 
                        <input type="hidden" value="${file.path}" name="org_files">
 
                        <input id="filename_${h.FID('f',file.path)}" name="files" size="30" type="text" value="${file.path}">
 

	
 
                        <select id="mimetype_${h.FID('f',file.path)}" name="mimetypes">
 
                            <option selected="selected" value="plain">${_('plain')}</option>
 
                        </select>
 
                    </div>
 
                    <div class="editor_container">
 
                        <pre id="editor_pre"></pre>
 
                        <textarea id="editor_${h.FID('f',file.path)}" name="contents" style="display:none">${file.content}</textarea>
 
                    </div>
 
                </div>
 

	
 
                ## dynamic edit box.
 
                <script type="text/javascript">
 
                var myCodeMirror = initCodeMirror("editor_${h.FID('f',file.path)}", '');
 
                CodeMirror.modeURL = "${h.url('/js/mode/%N/%N.js')}";
 

	
 
                //inject new modes
 
                var modes_select = $('#mimetype_${h.FID('f',file.path)}');
 
                for(var i=0;i<CodeMirror.modeInfo.length;i++){
 
                    var m = CodeMirror.modeInfo[i];
 
                    var opt = new Option(m.name, m.mime);
 
                    YUD.setAttribute(opt, 'mode', m.mode)
 
                    modes_select[0].options[i+1] = opt;
 
                }
 

	
kallithea/templates/admin/gists/index.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    %if c.show_private:
 
        ${_('Private Gists for user %s') % c.rhodecode_user.username}
 
        ${_('Private Gists for user %s') % c.authuser.username}
 
    %elif c.show_public:
 
        ${_('Public Gists for user %s') % c.rhodecode_user.username}
 
        ${_('Public Gists for user %s') % c.authuser.username}
 
    %else:
 
        ${_('Public Gists')}
 
    %endif
 
    %if c.rhodecode_name:
 
        &middot; ${c.rhodecode_name}
 
    %endif
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    %if c.show_private:
 
        ${_('Private Gists for user %s') % c.rhodecode_user.username}
 
        ${_('Private Gists for user %s') % c.authuser.username}
 
    %elif c.show_public:
 
        ${_('Public Gists for user %s') % c.rhodecode_user.username}
 
        ${_('Public Gists for user %s') % c.authuser.username}
 
    %else:
 
        ${_('Public Gists')}
 
    %endif
 
    - ${c.gists_pager.item_count}
 
</%def>
 

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

	
 
<%def name="main()">
 
<div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
        %if c.rhodecode_user.username != 'default':
 
        %if c.authuser.username != 'default':
 
        <ul class="links">
 
          <li>
 
             <a href="${h.url('new_gist')}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_(u'Create New Gist')}</a>
 
          </li>
 
        </ul>
 
        %endif
 
    </div>
 
    %if c.gists_pager.item_count>0:
 
        % for gist in c.gists_pager:
 
          <div class="gist-item" style="padding:10px 20px 10px 15px">
 

	
 
            <div class="gravatar">
 
               <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(gist.owner.full_contact),28)}"/>
 
            </div>
 
            <div title="${gist.owner.full_contact}" class="user" style="font-size: 16px">
 
                <b>${h.person(gist.owner.full_contact)}</b> /
 
                <b><a href="${h.url('gist',gist_id=gist.gist_access_id)}">gist: ${gist.gist_access_id}</a></b>
 
            </div>
 
            <div style="padding: 4px 0px 0px 0px">
 
                ${_('Created')} ${h.age(gist.created_on)} /
 
                <span style="color: #AAA">
 
                  %if gist.gist_expires == -1:
 
                   ${_('Expires')}: ${_('never')}
 
                  %else:
 
                   ${_('Expires')}: ${h.age(h.time_to_datetime(gist.gist_expires))}
 
                  %endif
 
                </span>
 
            </div>
 

	
 
            <div style="border:0px;padding:10px 0px 0px 40px;color:#AAA">${gist.gist_description}</div>
 
          </div>
 
        % endfor
 

	
 
        <div class="notification-paginator">
 
          <div class="pagination-wh pagination-left">
 
          ${c.gists_pager.pager('$link_previous ~2~ $link_next', **request.GET.mixed())}
 
          </div>
 
        </div>
 
    %else:
 
        <div class="table">${_('There are no gists yet')}</div>
 
    %endif
 
</div>
 
</%def>
kallithea/templates/admin/gists/new.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('New Gist')}
 
    %if c.rhodecode_name:
 
        &middot; ${c.rhodecode_name}
 
    %endif
 
</%def>
 

	
 
<%def name="js_extra()">
 
<script type="text/javascript" src="${h.url('/js/codemirror.js')}"></script>
 
<script type="text/javascript" src="${h.url('/js/codemirror_loadmode.js')}"></script>
 
<script type="text/javascript" src="${h.url('/js/mode/meta.js')}"></script>
 
<script type="text/javascript" src="${h.url('/js/mode/meta_ext.js')}"></script>
 
</%def>
 
<%def name="css_extra()">
 
<link rel="stylesheet" type="text/css" href="${h.url('/css/codemirror.css')}"/>
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${_('New Gist')}
 
</%def>
 

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

	
 
<%def name="main()">
 
<div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
    </div>
 

	
 
    <div class="table">
 
        <div id="files_data">
 
          ${h.form(h.url('gists'), method='post',id='eform')}
 
            <div>
 
                <div class="gravatar">
 
                   <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(c.rhodecode_user.full_contact),32)}"/>
 
                   <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(c.authuser.full_contact),32)}"/>
 
                </div>
 
                <textarea style="resize:vertical; width:400px;border: 1px solid #ccc;border-radius: 3px;" id="description" name="description" placeholder="${_('Gist description ...')}"></textarea>
 
                <div style="padding:0px 0px 0px 42px">
 
                <label for='lifetime'>${_('Gist lifetime')}</label>
 
                ${h.select('lifetime', '', c.lifetime_options)}
 
                </div>
 
            </div>
 
            <div id="body" class="codeblock">
 
                <div style="padding: 10px 10px 10px 26px;color:#666666">
 
                    ${h.text('filename', size=30, placeholder=_('name this file...'))}
 
                    ${h.select('mimetype','plain',[('plain',_('plain'))])}
 
                </div>
 
                <div id="editor_container">
 
                    <pre id="editor_pre"></pre>
 
                    <textarea id="editor" name="content" style="display:none"></textarea>
 
                </div>
 
            </div>
 
            <div style="padding-top: 5px">
 
            ${h.submit('private',_('Create Private Gist'),class_="btn btn-mini btn-success")}
 
            ${h.submit('public',_('Create Public Gist'),class_="btn btn-mini")}
 
            ${h.reset('reset',_('Reset'),class_="btn btn-mini")}
 
            </div>
 
            ${h.end_form()}
 
            <script type="text/javascript">
 
            var myCodeMirror = initCodeMirror('editor', '');
 
            CodeMirror.modeURL = "${h.url('/js/mode/%N/%N.js')}";
 

	
 
            //inject new modes
 
            var modes_select = $('#mimetype');
 
            for(var i=0;i<CodeMirror.modeInfo.length;i++){
 
                var m = CodeMirror.modeInfo[i];
 
                var opt = new Option(m.name, m.mime);
 
                YUD.setAttribute(opt, 'mode', m.mode)
 
                modes_select[0].options[i+1] = opt;
 
            }
 

	
 
            var filename_selector = '#filename';
 
            // on select change set new mode
 
            modes_select.on('change', function(e){
 
                var selected = e.currentTarget;
 
                var node = selected.options[selected.selectedIndex];
 
                var mimetype = node.value;
 
                var new_mode = YUD.getAttribute(node, 'mode')
 
                setCodeMirrorMode(myCodeMirror, new_mode);
 

	
 
                var proposed_ext = getExtFromMimeType(mimetype);
 
                var file_data = getFilenameAndExt($(filename_selector).val());
 
                var filename = file_data['filename'] || 'filename1';
kallithea/templates/admin/gists/show.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('Gist')} &middot; ${c.gist.gist_access_id}
 
    %if c.rhodecode_name:
 
        &middot; ${c.rhodecode_name}
 
    %endif
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${_('Gist')} &middot; ${c.gist.gist_access_id}
 
    / ${_('URL')}: ${c.gist.gist_url()}
 
</%def>
 

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

	
 
<%def name="main()">
 
<div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
        %if c.rhodecode_user.username != 'default':
 
        %if c.authuser.username != 'default':
 
        <ul class="links">
 
          <li>
 
              <a href="${h.url('new_gist')}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_(u'Create New Gist')}</a>
 
          </li>
 
        </ul>
 
        %endif
 
    </div>
 
    <div class="table">
 
        <div id="files_data">
 
            <div id="body" class="codeblock">
 
                <div class="code-header">
 
                    <div class="stats">
 
                        <div class="left" style="margin: -4px 0px 0px 0px">
 
                          %if c.gist.gist_type == 'public':
 
                            <div class="btn btn-mini btn-success disabled">${_('Public Gist')}</div>
 
                          %else:
 
                            <div class="btn btn-mini btn-warning disabled">${_('Private Gist')}</div>
 
                          %endif
 
                        </div>
 
                        <div class="left item">
 
                            ${c.gist.gist_description}
 
                        </div>
 
                        <div class="left item last" style="color: #AAA">
 
                         %if c.gist.gist_expires == -1:
 
                          ${_('Expires')}: ${_('never')}
 
                         %else:
 
                          ${_('Expires')}: ${h.age(h.time_to_datetime(c.gist.gist_expires))}
 
                         %endif
 
                       </div>
 

	
 
                       %if h.HasPermissionAny('hg.admin')() or c.gist.gist_owner == c.rhodecode_user.user_id:
 
                       %if h.HasPermissionAny('hg.admin')() or c.gist.gist_owner == c.authuser.user_id:
 
                        <div style="float:right">
 
                            ${h.form(url('gist', gist_id=c.gist.gist_id),method='delete')}
 
                                ${h.submit('remove_gist', _('Delete'),class_="btn btn-mini btn-danger",onclick="return confirm('"+_('Confirm to delete this Gist')+"');")}
 
                            ${h.end_form()}
 
                        </div>
 
                       %endif
 
                        <div class="buttons">
 
                          ## only owner should see that
 
                          %if h.HasPermissionAny('hg.admin')() or c.gist.gist_owner == c.rhodecode_user.user_id:
 
                          %if h.HasPermissionAny('hg.admin')() or c.gist.gist_owner == c.authuser.user_id:
 
                            ${h.link_to(_('Edit'),h.url('edit_gist', gist_id=c.gist.gist_access_id),class_="btn btn-mini")}
 
                          %endif
 
                          ${h.link_to(_('Show as Raw'),h.url('formatted_gist', gist_id=c.gist.gist_access_id, format='raw'),class_="btn btn-mini")}
 
                        </div>
 
                    </div>
 

	
 
                    <div class="author">
 
                        <div class="gravatar">
 
                            <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(c.file_changeset.author),16)}"/>
 
                        </div>
 
                        <div title="${c.file_changeset.author}" class="user">${h.person(c.file_changeset.author)} - ${_('created')} ${h.age(c.file_changeset.date)}</div>
 
                    </div>
 
                    <div class="commit">${h.urlify_commit(c.file_changeset.message,c.repo_name)}</div>
 
                </div>
 
            </div>
 

	
 
               ## iterate over the files
 
               % for file in c.files:
 
               <div style="border: 1px solid #EEE;margin-top:20px">
 
                <div id="${h.FID('G', file.path)}" class="stats" style="border-bottom: 1px solid #DDD;padding: 8px 14px;">
 
                    <a href="${c.gist.gist_url()}">¶</a>
 
                    <b style="margin:0px 0px 0px 4px">${file.path}</b>
 
                    <div style="float:right; margin: -5px">
 
                       ${h.link_to(_('Show as raw'),h.url('formatted_gist_file', gist_id=c.gist.gist_access_id, format='raw', revision=file.changeset.raw_id, f_path=file.path),class_="btn btn-mini")}
 
                    </div>
 
                </div>
 
                <div class="code-body">
 
                    ${h.pygmentize(file,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
 
                </div>
 
              </div>
 
               %endfor
 
        </div>
 
    </div>
 

	
 

	
 
</div>
 
</%def>
kallithea/templates/admin/my_account/my_account.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('My account')} ${c.rhodecode_user.username}
 
    ${_('My account')} ${c.authuser.username}
 
    %if c.rhodecode_name:
 
        &middot; ${c.rhodecode_name}
 
    %endif
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${_('My Account')}
 
</%def>
 

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

	
 
<%def name="main()">
 
<div class="box" style="overflow:auto">
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
    </div>
 

	
 
    ##main
 
    <div style="width: 150px; float:left">
 
        <ul class="nav nav-pills nav-stacked">
 
          <li>
 
           <div class="gravatar_box" style="height: 26px">
 
               <div class="gravatar" style="float: left">
 
                   <img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/>
 
               </div>
 
               <div class="truncate" style="margin:10px 0px 10px 0px; color:#5f5f5f; float:left; width: 100px">
 
                <strong>${c.user.username}</strong>
 
               </div>
 
           </div>
 
          </li>
 
          <li class="${'active' if c.active=='profile' else ''}"><a href="${h.url('my_account')}">${_('Profile')}</a></li>
 
          <li class="${'active' if c.active=='password' else ''}"><a href="${h.url('my_account_password')}">${_('Password')}</a></li>
 
          <li class="${'active' if c.active=='api_keys' else ''}"><a href="${h.url('my_account_api_keys')}">${_('API keys')}</a></li>
 
          <li class="${'active' if c.active=='emails' else ''}"><a href="${h.url('my_account_emails')}">${_('My Emails')}</a></li>
 
          <li class="${'active' if c.active=='repos' else ''}"><a href="${h.url('my_account_repos')}">${_('My Repositories')}</a></li>
 
          <li class="${'active' if c.active=='watched' else ''}"><a href="${h.url('my_account_watched')}">${_('Watched')}</a></li>
 
          <li class="${'active' if c.active=='pullrequests' else ''}"><a href="${h.url('my_account_pullrequests')}">${_('Pull requests')}</a></li>
 
          <li class="${'active' if c.active=='perms' else ''}"><a href="${h.url('my_account_perms')}">${_('My permissions')}</a></li>
 
        </ul>
 
    </div>
 

	
 
    <div style="min-width:750px; float:left; padding: 10px 0px 0px 20px;margin: 0px 0px 0px 10px; border-left: 1px solid #DDDDDD">
 
        <%include file="/admin/my_account/my_account_${c.active}.html"/>
 
    </div>
 
</div>
 

	
kallithea/templates/admin/notifications/notifications.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('My Notifications')} ${c.rhodecode_user.username}
 
    ${_('My Notifications')} ${c.authuser.username}
 
    %if c.rhodecode_name:
 
        &middot; ${c.rhodecode_name}
 
    %endif
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${_('My Notifications')}
 
</%def>
 

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

	
 
<%def name="main()">
 
<div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
        ##<ul class="links">
 
        ##    <li>
 
        ##      <span style="text-transform: uppercase;"><a href="#">${_('Compose message')}</a></span>
 
        ##    </li>
 
        ##</ul>
 
    </div>
 

	
 
      <div style="padding:14px 18px;text-align: right;float:left">
 
      <span id='all' class="btn btn-mini"><a href="${h.url.current()}">${_('All')}</a></span>
 
      <span id='comment' class="btn btn-mini"><a href="${h.url.current(type=c.comment_type)}">${_('Comments')}</a></span>
 
      <span id='pull_request' class="btn btn-mini"><a href="${h.url.current(type=c.pull_request_type)}">${_('Pull Requests')}</a></span>
 
      </div>
 
      %if c.notifications:
 
      <div style="padding:14px 18px;text-align: right;float:right">
 
      <span id='mark_all_read' class="btn btn-mini">${_('Mark all read')}</span>
 
      </div>
 
      %endif
 
  <div id='notification_data'>
 
    <%include file='notifications_data.html'/>
 
  </div>
 
</div>
 
<script type="text/javascript">
 
var url_action = "${url('notification', notification_id='__NOTIFICATION_ID__')}";
 
var run = function(){
 
  YUE.on(YUQ('.delete-notification'),'click',function(e){
 
   var notification_id = e.currentTarget.id;
 
   deleteNotification(url_action,notification_id)
 
  })
 
  YUE.on(YUQ('.read-notification'),'click',function(e){
 
     var notification_id = e.currentTarget.id;
kallithea/templates/admin/notifications/show_notification.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('Show notification')} ${c.rhodecode_user.username}
 
    ${_('Show notification')} ${c.authuser.username}
 
    %if c.rhodecode_name:
 
        &middot; ${c.rhodecode_name}
 
    %endif
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${h.link_to(_('Notifications'),h.url('notifications'))}
 
    &raquo;
 
    ${_('Show notification')}
 
</%def>
 

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

	
 
<%def name="main()">
 
<div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
        ##<ul class="links">
 
        ##    <li>
 
        ##      <span style="text-transform: uppercase;"><a href="#">${_('Compose message')}</a></span>
 
        ##    </li>
 
        ##</ul>
 
    </div>
 
    <div class="table">
 
      <div id="notification_${c.notification.notification_id}">
 
        <div class="notification-header">
 
          <div class="gravatar">
 
              <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(c.notification.created_by_user.email),24)}"/>
 
          </div>
 
          <div class="desc">
 
              ${c.notification.description}
 
          </div>
 
          <div class="delete-notifications">
 
            <span id="${c.notification.notification_id}" class="delete-notification action"><i class="icon-minus-sign" id="yui-gen24"></i></span>
 
          </div>
 
        </div>
 
        <div class="notification-body">
 
        <div class="notification-subject">${h.literal(c.notification.subject)}</div>
 
        %if c.notification.body:
 
            ${h.rst_w_mentions(c.notification.body)}
 
        %endif
 
        </div>
 
      </div>
 
    </div>
 
</div>
kallithea/templates/admin/repo_groups/repo_group_edit_perms.html
Show inline comments
 
${h.form(url('edit_repo_group_perms', group_name=c.repo_group.group_name),method='put')}
 
<div class="form">
 
   <div class="fields">
 
        <div class="field">
 
            <table id="permissions_manage" class="noborder">
 
                <tr>
 
                    <td>${_('none')}</td>
 
                    <td>${_('read')}</td>
 
                    <td>${_('write')}</td>
 
                    <td>${_('admin')}</td>
 
                    <td>${_('user/user group')}</td>
 
                    <td></td>
 
                </tr>
 
                ## USERS
 
                %for r2p in c.repo_group.repo_group_to_perm:
 
                    ##forbid revoking permission from yourself, except if you're an super admin
 
                    <tr id="id${id(r2p.user.username)}">
 
                        %if c.rhodecode_user.user_id != r2p.user.user_id or c.rhodecode_user.is_admin:
 
                        %if c.authuser.user_id != r2p.user.user_id or c.authuser.is_admin:
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'group.none')}</td>
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'group.read')}</td>
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'group.write')}</td>
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'group.admin')}</td>
 
                        <td style="white-space: nowrap;">
 
                            <img class="perm-gravatar" src="${h.gravatar_url(r2p.user.email,14)}"/>
 
                            %if h.HasPermissionAny('hg.admin')() and r2p.user.username != 'default':
 
                             <a href="${h.url('edit_user',id=r2p.user.user_id)}">${r2p.user.username}</a>
 
                            %else:
 
                             ${r2p.user.username if r2p.user.username != 'default' else _('default')}
 
                            %endif
 
                        </td>
 
                        <td>
 
                          %if r2p.user.username !='default':
 
                            <span style="color:#da4f49" class="action_button" onclick="ajaxActionRevoke(${r2p.user.user_id}, 'user', '${'id%s'%id(r2p.user.username)}', '${r2p.user.username}')">
 
                             <i class="icon-remove"></i> ${_('revoke')}
 
                            </span>
 
                          %endif
 
                        </td>
 
                        %else:
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'group.none', disabled="disabled")}</td>
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'group.read', disabled="disabled")}</td>
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'group.write', disabled="disabled")}</td>
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'group.admin', disabled="disabled")}</td>
 
                        <td style="white-space: nowrap;">
 
                            <img class="perm-gravatar" src="${h.gravatar_url(r2p.user.email,14)}"/>
 
                            ${r2p.user.username if r2p.user.username != 'default' else _('default')}
 
                        </td>
 
                        <td><i class="icon-user"></i> ${_('delegated admin')}</td>
 
                        %endif
 
                    </tr>
 
                %endfor
 

	
 
                ## USER GROUPS
 
                %for g2p in c.repo_group.users_group_to_perm:
 
                    <tr id="id${id(g2p.users_group.users_group_name)}">
 
                        <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.none')}</td>
 
                        <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.read')}</td>
 
                        <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.write')}</td>
 
                        <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.admin')}</td>
 
                        <td style="white-space: nowrap;">
 
                            <img class="perm-gravatar" src="${h.url('/images/icons/group.png')}"/>
 
                            %if h.HasPermissionAny('hg.admin')():
 
                             <a href="${h.url('edit_users_group',id=g2p.users_group.users_group_id)}">
 
                                 ${g2p.users_group.users_group_name}
 
                             </a>
 
                            %else:
 
                             ${g2p.users_group.users_group_name}
kallithea/templates/admin/repos/repo_add.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('Add repository')}
 
    %if c.rhodecode_name:
 
        &middot; ${c.rhodecode_name}
 
    %endif
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    %if c.rhodecode_user.is_admin:
 
    %if c.authuser.is_admin:
 
    ${h.link_to(_('Admin'),h.url('admin_home'))}
 
    &raquo;
 
    ${h.link_to(_('Repositories'),h.url('repos'))}
 
    %else:
 
    ${_('Admin')}
 
    &raquo;
 
    ${_('Repositories')}
 
    %endif
 
    &raquo;
 
    ${_('Add Repository')}
 
</%def>
 

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

	
 
<%def name="main()">
 
    <div class="box">
 
        <!-- box / title -->
 
        <div class="title">
 
            ${self.breadcrumbs()}
 
        </div>
 
        <%include file="repo_add_base.html"/>
 
    </div>
 
</%def>
kallithea/templates/admin/repos/repo_add_base.html
Show inline comments
 
## -*- coding: utf-8 -*-
 

	
 
${h.form(url('repos'))}
 
<div class="form">
 
    <!-- fields -->
 
    <div class="fields">
 
        <div class="field">
 
            <div class="label">
 
                <label for="repo_name">${_('Name')}:</label>
 
            </div>
 
            <div class="input">
 
                ${h.text('repo_name',class_="small")}
 
                <div style="margin: 6px 0px 0px 0px">
 
                    <a id="remote_clone_toggle" href="#"><i class="icon-download-alt"></i> ${_('Import existing repository ?')}</a>
 
                </div>
 
                %if not c.rhodecode_user.is_admin:
 
                %if not c.authuser.is_admin:
 
                    ${h.hidden('user_created',True)}
 
                %endif
 
            </div>
 
         </div>
 
        <div id="remote_clone" class="field" style="display: none">
 
            <div class="label">
 
                <label for="clone_uri">${_('Clone from')}:</label>
 
            </div>
 
            <div class="input">
 
                ${h.text('clone_uri',class_="small")}
 
                <span class="help-block">${_('Optional http[s] url from which repository should be cloned.')}</span>
 
            </div>
 
        </div>
 
        <div class="field">
 
            <div class="label label-textarea">
 
                <label for="repo_description">${_('Description')}:</label>
 
            </div>
 
            <div class="textarea-repo editor">
 
                ${h.textarea('repo_description')}
 
                <span class="help-block">${_('Keep it short and to the point. Use a README file for longer descriptions.')}</span>
 
            </div>
 
        </div>
 
        <div class="field">
 
             <div class="label">
 
                 <label for="repo_group">${_('Repository group')}:</label>
 
             </div>
 
             <div class="input">
 
                 ${h.select('repo_group',request.GET.get('parent_group'),c.repo_groups,class_="medium")}
 
                 <span class="help-block">${_('Optionaly select a group to put this repository into.')}</span>
 
             </div>
 
        </div>
 
        <div id="copy_perms" class="field">
 
            <div class="label label-checkbox">
 
                <label for="repo_copy_permissions">${_('Copy parent group permissions')}:</label>
 
            </div>
 
            <div class="checkboxes">
 
                ${h.checkbox('repo_copy_permissions',value="True")}
 
                <span class="help-block">${_('Copy permission set from parent repository group.')}</span>
 
            </div>
 
        </div>
 
        <div class="field">
 
            <div class="label">
 
                <label for="repo_type">${_('Type')}:</label>
 
            </div>
 
            <div class="input">
 
                ${h.select('repo_type','hg',c.backends,class_="small")}
 
                <span class="help-block">${_('Type of repository to create.')}</span>
 
            </div>
kallithea/templates/admin/user_groups/user_group_edit_perms.html
Show inline comments
 
${h.form(url('edit_user_group_perms', id=c.user_group.users_group_id),method='put')}
 
<div class="form">
 
   <div class="fields">
 
        <div class="field">
 
            <table id="permissions_manage" class="noborder">
 
                <tr>
 
                    <td>${_('none')}</td>
 
                    <td>${_('read')}</td>
 
                    <td>${_('write')}</td>
 
                    <td>${_('admin')}</td>
 
                    <td>${_('user/user group')}</td>
 
                    <td></td>
 
                </tr>
 
                ## USERS
 
                %for r2p in c.user_group.user_user_group_to_perm:
 
                    ##forbid revoking permission from yourself, except if you're an super admin
 
                    <tr id="id${id(r2p.user.username)}">
 
                        %if c.rhodecode_user.user_id != r2p.user.user_id or c.rhodecode_user.is_admin:
 
                        %if c.authuser.user_id != r2p.user.user_id or c.authuser.is_admin:
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'usergroup.none')}</td>
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'usergroup.read')}</td>
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'usergroup.write')}</td>
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'usergroup.admin')}</td>
 
                        <td style="white-space: nowrap;">
 
                            <img class="perm-gravatar" src="${h.gravatar_url(r2p.user.email,14)}"/>
 
                            %if h.HasPermissionAny('hg.admin')() and r2p.user.username != 'default':
 
                             <a href="${h.url('edit_user',id=r2p.user.user_id)}">${r2p.user.username}</a>
 
                            %else:
 
                             ${r2p.user.username if r2p.user.username != 'default' else _('default')}
 
                            %endif
 
                        </td>
 
                        <td>
 
                          %if r2p.user.username !='default':
 
                            <span style="color:#da4f49" class="action_button" onclick="ajaxActionRevoke(${r2p.user.user_id}, 'user', '${'id%s'%id(r2p.user.username)}', '${r2p.user.username}')">
 
                             <i class="icon-remove"></i> ${_('revoke')}
 
                            </span>
 
                          %endif
 
                        </td>
 
                        %else:
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'usergroup.none', disabled="disabled")}</td>
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'usergroup.read', disabled="disabled")}</td>
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'usergroup.write', disabled="disabled")}</td>
 
                        <td>${h.radio('u_perm_%s' % r2p.user.username,'usergroup.admin', disabled="disabled")}</td>
 
                        <td style="white-space: nowrap;">
 
                            <img class="perm-gravatar" src="${h.gravatar_url(r2p.user.email,14)}"/>
 
                            ${r2p.user.username if r2p.user.username != 'default' else _('default')}
 
                        </td>
 
                        <td><i class="icon-user"></i> ${_('delegated admin')}</td>
 
                        %endif
 
                    </tr>
 
                %endfor
 

	
 
                ## USER GROUPS
 
                %for g2p in c.user_group.user_group_user_group_to_perm:
 
                    <tr id="id${id(g2p.user_group.users_group_name)}">
 
                        <td>${h.radio('g_perm_%s' % g2p.user_group.users_group_name,'usergroup.none')}</td>
 
                        <td>${h.radio('g_perm_%s' % g2p.user_group.users_group_name,'usergroup.read')}</td>
 
                        <td>${h.radio('g_perm_%s' % g2p.user_group.users_group_name,'usergroup.write')}</td>
 
                        <td>${h.radio('g_perm_%s' % g2p.user_group.users_group_name,'usergroup.admin')}</td>
 
                        <td style="white-space: nowrap;">
 
                            <img class="perm-gravatar" src="${h.url('/images/icons/group.png')}"/>
 
                            %if h.HasPermissionAny('hg.admin')():
 
                             <a href="${h.url('edit_users_group',id=g2p.user_group.users_group_id)}">
 
                                 ${g2p.user_group.users_group_name}
 
                             </a>
 
                            %else:
 
                             ${g2p.user_group.users_group_name}
kallithea/templates/admin/users/user_edit_profile.html
Show inline comments
 
${h.form(url('update_user', id=c.user.user_id),method='put')}
 
<div class="form">
 
        <div class="field">
 
           <div class="gravatar_box">
 
               <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
 
                <p>
 
                %if c.visual.use_gravatar:
 
                <strong>${_('Change avatar at')} <a href="http://gravatar.com">gravatar.com</a></strong>
 
                <br/>${_('Using')} ${c.user.email}
 
                %else:
 
                <strong>${_('Avatars are disabled')}</strong>
 
                <br/>${c.user.email or _('Missing email, please update this user email address.')}
 
                        ##show current ip just if we show ourself
 
                        %if c.rhodecode_user.username == c.user.username:
 
                        %if c.authuser.username == c.user.username:
 
                            [${_('current IP')}: ${c.perm_user.ip_addr or "?"}]
 
                        %endif
 
                %endif
 
           </div>
 
        </div>
 
        <% readonly = None %>
 
        <% disabled = "" %>
 
        <div class="fields">
 
            %if c.extern_type != 'rhodecode':
 
             <div class="field">
 
               <% readonly = "readonly" %>
 
               <% disabled = " disabled" %>
 
               <strong>${_('This user is in an external Source of Record (%s); some details cannot be managed here.' % c.extern_type)}.</strong>
 
             </div>
 
            %endif
 

	
 
             <div class="field">
 
                <div class="label">
 
                    <label for="username">${_('Username')}:</label>
 
                </div>
 
                <div class="input">
 
                  ${h.text('username',class_='medium%s' % disabled, readonly=readonly)}
 
                </div>
 
             </div>
 

	
 
             <div class="field">
 
                <div class="label">
 
                    <label for="email">${_('Email')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.text('email',class_='medium')}
 
                </div>
 
             </div>
 

	
 
             <div class="field">
 
                <div class="label">
 
                    <label for="extern_type">${_('Source of Record')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.text('extern_type',class_='medium disabled',readonly="readonly")}
 
                </div>
 
             </div>
 

	
 
             <div class="field">
 
                <div class="label">
 
                    <label for="extern_name">${_('Name in Source of Record')}:</label>
 
                </div>
 
                <div class="input">
kallithea/templates/base/base.html
Show inline comments
 
@@ -133,270 +133,270 @@
 
        %if current == 'createfork':
 
         - ${_('Create fork')}
 
        %endif
 
      </h2>
 
      <!--
 
      <div id="breadcrumbs">
 
        ${h.link_to(_(u'Repositories'),h.url('home'))}
 
        &raquo;
 
        ${h.repo_link(c.db_repo.groups_and_repo)}
 
      </div>
 
      -->
 
      <ul id="context-pages" class="horizontal-list">
 
        <li ${is_current('summary')}><a href="${h.url('summary_home', repo_name=c.repo_name)}"><i class="icon-file-text"></i> ${_('Summary')}</a></li>
 
        <li ${is_current('changelog')}><a href="${h.url('changelog_home', repo_name=c.repo_name)}"><i class="icon-time"></i> ${_('Changelog')}</a></li>
 
        <li ${is_current('files')}><a href="${h.url('files_home', repo_name=c.repo_name)}"><i class="icon-file"></i> ${_('Files')}</a></li>
 
        <li ${is_current('switch-to')}>
 
          <a href="#" id="branch_tag_switcher_2" class="dropdown"><i class="icon-random"></i> ${_('Switch To')}</a>
 
          <ul id="switch_to_list_2" class="switch_to submenu">
 
            <li><a href="#">${_('Loading...')}</a></li>
 
          </ul>
 
        </li>
 
        <li ${is_current('options')}>
 
             %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
 
               <a href="${h.url('edit_repo',repo_name=c.repo_name)}" class="dropdown"><i class="icon-cogs"></i> ${_('Options')}</a>
 
             %else:
 
               <a href="#" class="dropdown"><i class="icon-cogs"></i> ${_('Options')}</a>
 
             %endif
 
          <ul>
 
             %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
 
                   <li><a href="${h.url('edit_repo',repo_name=c.repo_name)}"><i class="icon-cog"></i> ${_('Settings')}</a></li>
 
             %endif
 
              %if c.db_repo.fork:
 
               <li><a href="${h.url('compare_url',repo_name=c.db_repo.fork.repo_name,org_ref_type=c.db_repo.landing_rev[0],org_ref=c.db_repo.landing_rev[1], other_repo=c.repo_name,other_ref_type='branch' if request.GET.get('branch') else c.db_repo.landing_rev[0],other_ref=request.GET.get('branch') or c.db_repo.landing_rev[1], merge=1)}">
 
                   <i class="icon-loop"></i> ${_('Compare fork')}</a></li>
 
              %endif
 
              <li><a href="${h.url('compare_home',repo_name=c.repo_name)}"><i class="icon-loop"></i> ${_('Compare')}</a></li>
 

	
 
              <li><a href="${h.url('search_repo',repo_name=c.repo_name)}"><i class="icon-search"></i> ${_('Search')}</a></li>
 

	
 
              %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.db_repo.enable_locking:
 
                %if c.db_repo.locked[0]:
 
                  <li>${h.link_to(_('Unlock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_del')}</li>
 
                %else:
 
                  <li>${h.link_to(_('Lock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_add')}</li>
 
                %endif
 
              %endif
 
              ## TODO: this check feels wrong, it would be better to have a check for permissions
 
              ## also it feels like a job for the controller
 
              %if c.rhodecode_user.username != 'default':
 
              %if c.authuser.username != 'default':
 
                  <li>
 
                   <a class="${follow_class()}" onclick="javascript:toggleFollowingRepo(this,${c.db_repo.repo_id},'${str(h.get_token())}');">
 
                    <span class="show-follow"><i class="icon-heart-empty"></i> ${_('Follow')}</span>
 
                    <span class="show-following"><i class="icon-heart"></i> ${_('Unfollow')}</span>
 
                  </a>
 
                  </li>
 
                  <li><a href="${h.url('repo_fork_home',repo_name=c.repo_name)}"><i class="icon-code-fork"></i> ${_('Fork')}</a></li>
 
                  %if h.is_hg(c.db_repo_scm_instance):
 
                  <li><a href="${h.url('pullrequest_home',repo_name=c.repo_name)}"><i class="icon-code-fork"></i> ${_('Create Pull Request')}</a></li>
 
                  %endif
 
              %endif
 
             </ul>
 
        </li>
 
        <li ${is_current('showpullrequest')}>
 
          <a href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}" title="${_('Show Pull Requests for %s') % c.repo_name}"> <i class="icon-code-fork"></i> ${_('Pull Requests')}
 
            %if c.repository_pull_requests:
 
              <span>${c.repository_pull_requests}</span>
 
            %endif
 
          </a>
 
        </li>
 
      </ul>
 
  </div>
 
  <script type="text/javascript">
 
      YUE.on('branch_tag_switcher_2','mouseover',function(){
 
         var loaded = YUD.hasClass('branch_tag_switcher_2','loaded');
 
         if(!loaded){
 
             YUD.addClass('branch_tag_switcher_2','loaded');
 
             ypjax("${h.url('branch_tag_switcher',repo_name=c.repo_name)}",'switch_to_list_2',
 
                 function(o){},
 
                 function(o){YUD.removeClass('branch_tag_switcher_2','loaded');}
 
                 ,null);
 
         }
 
         return false;
 
      });
 
  </script>
 
  <!--- END CONTEXT BAR -->
 
</%def>
 

	
 
<%def name="usermenu()">
 
    ## USER MENU
 
    <li>
 
      <a class="menu_link childs" id="quick_login_link">
 
          <span class="icon">
 
             <img src="${h.gravatar_url(c.rhodecode_user.email,20)}" alt="avatar">
 
             <img src="${h.gravatar_url(c.authuser.email,20)}" alt="avatar">
 
          </span>
 
          %if c.rhodecode_user.username != 'default':
 
            <span class="menu_link_user">${c.rhodecode_user.username}</span>
 
          %if c.authuser.username != 'default':
 
            <span class="menu_link_user">${c.authuser.username}</span>
 
            %if c.unread_notifications != 0:
 
              <span class="menu_link_notifications">${c.unread_notifications}</span>
 
            %endif
 
          %else:
 
              <span>${_('Not logged in')}</span>
 
          %endif
 
      </a>
 

	
 
  <div class="user-menu">
 
      <div id="quick_login">
 
        %if c.rhodecode_user.username == 'default':
 
        %if c.authuser.username == 'default':
 
            <h4>${_('Login to your account')}</h4>
 
            ${h.form(h.url('login_home',came_from=h.url.current()))}
 
            <div class="form">
 
                <div class="fields">
 
                    <div class="field">
 
                        <div class="label">
 
                            <label for="username">${_('Username')}:</label>
 
                        </div>
 
                        <div class="input">
 
                            ${h.text('username',class_='focus')}
 
                        </div>
 

	
 
                    </div>
 
                    <div class="field">
 
                        <div class="label">
 
                            <label for="password">${_('Password')}:</label>
 
                        </div>
 
                        <div class="input">
 
                            ${h.password('password',class_='focus')}
 
                        </div>
 

	
 
                    </div>
 
                    <div class="buttons">
 
                        <div class="password_forgoten">${h.link_to(_('Forgot password ?'),h.url('reset_password'))}</div>
 
                        <div class="register">
 
                        %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
 
                         ${h.link_to(_("Don't have an account ?"),h.url('register'))}
 
                        %endif
 
                        </div>
 
                        <div class="submit">
 
                            ${h.submit('sign_in',_('Log In'),class_="btn btn-mini")}
 
                        </div>
 
                    </div>
 
                </div>
 
            </div>
 
            ${h.end_form()}
 
        %else:
 
            <div class="links_left">
 
                <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,48)}" /></div>
 
                <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
 
                <div class="email">${c.rhodecode_user.email}</div>
 
                <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.authuser.email,48)}" /></div>
 
                <div class="full_name">${c.authuser.full_name_or_username}</div>
 
                <div class="email">${c.authuser.email}</div>
 
            </div>
 
            <div class="links_right">
 
            <ol class="links">
 
              <li><a href="${h.url('notifications')}">${_('Notifications')}: ${c.unread_notifications}</a></li>
 
              <li>${h.link_to(_(u'My account'),h.url('my_account'))}</li>
 
              <li class="logout">${h.link_to(_(u'Log Out'),h.url('logout_home'))}</li>
 
            </ol>
 
            </div>
 
        %endif
 
      </div>
 
  </div>
 

	
 
    </li>
 
</%def>
 

	
 
<%def name="menu(current=None)">
 
        <%
 
        def is_current(selected):
 
            if selected == current:
 
                return h.literal('class="current"')
 
        %>
 
        <ul id="quick" class="horizontal-list">
 
          <!-- repo switcher -->
 
          <li ${is_current('repositories')}>
 
            <input id="repo_switcher" name="repo_switcher" type="hidden">
 
          </li>
 

	
 
          ##ROOT MENU
 
          %if c.rhodecode_user.username != 'default':
 
          %if c.authuser.username != 'default':
 
            <li ${is_current('journal')}>
 
              <a class="menu_link" title="${_('Show recent activity')}"  href="${h.url('journal')}">
 
                <i class="icon-book"></i> ${_('Journal')}
 
              </a>
 
            </li>
 
          %else:
 
            <li ${is_current('journal')}>
 
              <a class="menu_link" title="${_('Public journal')}"  href="${h.url('public_journal')}">
 
                <i class="icon-book"></i> ${_('Public journal')}
 
              </a>
 
            </li>
 
          %endif
 
            <li ${is_current('gists')}>
 
              <a class="menu_link childs" title="${_('Show public gists')}"  href="${h.url('gists')}">
 
                <i class="icon-file-2"></i> ${_('Gists')}
 
              </a>
 
                <ul class="admin_menu">
 
                  <li><a href="${h.url('new_gist', public=1)}"><i class="icon-file-alt"></i> ${_('Create new gist')}</a></li>
 
                  <li><a href="${h.url('gists')}"><i class="icon-copy"></i> ${_('All public gists')}</a></li>
 
                  %if c.rhodecode_user.username != 'default':
 
                  %if c.authuser.username != 'default':
 
                    <li><a href="${h.url('gists', public=1)}"><i class="icon-copy"></i> ${_('My public gists')}</a></li>
 
                    <li><a href="${h.url('gists', private=1)}"><i class="icon-file-text"></i> ${_('My private gists')}</a></li>
 
                  %endif
 
                </ul>
 
            </li>
 
          <li ${is_current('search')}>
 
              <a class="menu_link" title="${_('Search in repositories')}"  href="${h.url('search')}">
 
                <i class="icon-search"></i> ${_('Search')}
 
              </a>
 
          </li>
 
          % if h.HasPermissionAll('hg.admin')('access admin main page'):
 
            <li ${is_current('admin')}>
 
              <a class="menu_link childs" title="${_('Admin')}" href="${h.url('admin_home')}">
 
                <i class="icon-cog"></i> ${_('Admin')}
 
              </a>
 
              ${admin_menu()}
 
            </li>
 
          % elif c.rhodecode_user.repositories_admin or c.rhodecode_user.repository_groups_admin or c.rhodecode_user.user_groups_admin:
 
          % elif c.authuser.repositories_admin or c.authuser.repository_groups_admin or c.authuser.user_groups_admin:
 
          <li ${is_current('admin')}>
 
              <a class="menu_link childs" title="${_('Admin')}">
 
                <i class="icon-cog"></i> ${_('Admin')}
 
              </a>
 
              ${admin_menu_simple(c.rhodecode_user.repositories_admin,
 
                                  c.rhodecode_user.repository_groups_admin,
 
                                  c.rhodecode_user.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
 
              ${admin_menu_simple(c.authuser.repositories_admin,
 
                                  c.authuser.repository_groups_admin,
 
                                  c.authuser.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
 
          </li>
 
          % endif
 
          ${usermenu()}
 

	
 
    <script type="text/javascript">
 
        var visual_show_public_icon = "${c.visual.show_public_icon}" == "True";
 
        var cache = {}
 
        /*format the look of items in the list*/
 
        var format = function(state){
 
            if (!state.id){
 
              return state.text; // optgroup
 
            }
 
            var obj_dict = state.obj;
 
            var tmpl = '';
 

	
 
            if(obj_dict && state.type == 'repo'){
 
                tmpl += '<span class="repo-icons">';
 
                if(obj_dict['repo_type'] === 'hg'){
 
                    tmpl += '<i class="icon-hg"></i> ';
 
                }
 
                else if(obj_dict['repo_type'] === 'git'){
 
                    tmpl += '<i class="icon-git"></i> ';
 
                }
 
                if(obj_dict['private']){
 
                    tmpl += '<i class="icon-lock" style="color: #e85634;"></i> ';
 
                }
 
                else if(visual_show_public_icon){
 
                    tmpl += '<i class="icon-unlock-alt"></i> ';
 
                }
 
                tmpl += '</span>';
 
            }
 
            if(obj_dict && state.type == 'group'){
 
                    tmpl += '<i class="icon-folder-close"></i> ';
 
            }
 
            tmpl += state.text;
 
            return tmpl;
 
        }
 

	
 
        $("#repo_switcher").select2({
 
            placeholder: '<i class="icon-archive"></i> ${_('Repositories')}',
 
            dropdownAutoWidth: true,
 
            formatResult: format,
 
            formatSelection: format,
 
            formatNoMatches: function(term){
 
                return "${_('No matches found')}";
 
            },
 
            containerCssClass: "repo-switcher",
 
            dropdownCssClass: "repo-switcher-dropdown",
kallithea/templates/changeset/changeset_file_comment.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
## usage:
 
## <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
 
## ${comment.comment_block(co)}
 
##
 
<%def name="comment_block(co)">
 
  <div class="comment" id="comment-${co.comment_id}" line="${co.line_no}">
 
    <div class="comment-wrapp">
 
      <div class="meta">
 
        <div style="float:left"> <img src="${h.gravatar_url(co.author.email, 20)}" /> </div>
 
          <div class="user">
 
              ${co.author.username}
 
          </div>
 
          <div class="date">
 
              ${h.age(co.modified_at)}
 
          </div>
 

	
 
       <div style="float:left;padding:4px 0px 0px 5px">
 
        <span class="">
 
         %if co.pull_request:
 
            <a href="${h.url('pullrequest_show',repo_name=co.pull_request.other_repo.repo_name,pull_request_id=co.pull_request.pull_request_id)}">
 
            %if co.status_change:
 
              ${_('Vote on pull request #%s') % co.pull_request.pull_request_id}:
 
            %else:
 
              ${_('Comment on pull request #%s') % co.pull_request.pull_request_id}
 
            %endif
 
            </a>
 
         %else:
 
            %if co.status_change:
 
              ${_('Status change on changeset')}:
 
            %else:
 
              ${_('Comment on changeset')}
 
            %endif
 
         %endif
 
        </span>
 
       </div>
 

	
 
        %if co.status_change:
 
           <div  style="float:left" class="changeset-status-container">
 
             <div style="float:left;padding:10px 2px 0px 2px"></div>
 
             <div title="${_('Changeset status')}" class="changeset-status-lbl"> ${co.status_change[0].status_lbl}</div>
 
             <div class="changeset-status-ico"><img src="${h.url(str('/images/icons/flag_status_%s.png' % co.status_change[0].status))}" /></div>
 
           </div>
 
        %endif
 

	
 
      <a class="permalink" href="#comment-${co.comment_id}">&para;</a>
 
      %if h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or co.author.user_id == c.rhodecode_user.user_id:
 
      %if h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or co.author.user_id == c.authuser.user_id:
 
          <div onClick="deleteComment(${co.comment_id})" class="buttons delete-comment btn btn-mini">${_('Delete')}</div>
 
      %endif
 
      </div>
 
      <div class="text">
 
          ${h.rst_w_mentions(co.text)|n}
 
      </div>
 
    </div>
 
  </div>
 
</%def>
 

	
 

	
 
<%def name="comment_inline_form()">
 
<div id='comment-inline-form-template' style="display:none">
 
  <div class="comment-inline-form ac">
 
  %if c.rhodecode_user.username != 'default':
 
  %if c.authuser.username != 'default':
 
    <div class="overlay"><div class="overlay-text">${_('Submitting...')}</div></div>
 
      ${h.form('#', class_='inline-form')}
 
      <div id="edit-container_{1}" class="clearfix">
 
          <div class="comment-help">${_('Commenting on line {1}.')}
 
          ${(_('Comments parsed using %s syntax with %s support.') % (
 
                 ('<a href="%s">RST</a>' % h.url('rst_help')),
 
                   ('<span style="color:#003367" class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user'))
 
               )
 
            )|n
 
           }
 
          <div id="preview-btn_{1}" class="preview-btn btn btn-mini">${_('Preview')}</div>
 
          </div>
 
            <div class="mentions-container" id="mentions_container_{1}"></div>
 
            <textarea id="text_{1}" name="text" class="comment-block-ta yui-ac-input"></textarea>
 
      </div>
 
      <div id="preview-container_{1}" class="clearfix" style="display:none">
 
         <div class="comment-help">
 
              ${_('Comment preview')}
 
            <div id="edit-btn_{1}" class="edit-btn btn btn-mini">${_('Edit')}</div>
 
          </div>
 
          <div id="preview-box_{1}" class="preview-box"></div>
 
      </div>
 
      <div class="comment-button">
 
      <input type="hidden" name="f_path" value="{0}">
 
      <input type="hidden" name="line" value="{1}">
 
      ${h.submit('save', _('Comment'), class_='btn btn-small save-inline-form')}
 
      ${h.reset('hide-inline-form', _('Cancel'), class_='btn btn-small hide-inline-form')}
 
      </div>
 
      ${h.end_form()}
 
  %else:
 
      ${h.form('')}
 
      <div class="clearfix">
 
          <div class="comment-help">
 
            ${_('You need to be logged in to comment.')} <a href="${h.url('login_home',came_from=h.url.current())}">${_('Login now')}</a>
 
          </div>
 
      </div>
 
      <div class="comment-button">
 
      ${h.reset('hide-inline-form', _('Hide'), class_='btn btn-small hide-inline-form')}
 
      </div>
 
      ${h.end_form()}
 
  %endif
 
  </div>
 
</div>
 
</%def>
 

	
 

	
 
## generates inlines taken from c.comments var
 
<%def name="inlines()">
 
    <div class="comments-number">${ungettext("%d comment", "%d comments", len(c.comments)) % len(c.comments)} ${ungettext("(%d inline)", "(%d inline)", c.inline_cnt) % c.inline_cnt}</div>
 
    %for path, lines in c.inline_comments:
 
        % for line,comments in lines.iteritems():
 
            <div style="display:none" class="inline-comment-placeholder" path="${path}" target_id="${h.safeid(h.safe_unicode(path))}">
 
            %for co in comments:
 
                ${comment_block(co)}
 
            %endfor
 
            </div>
 
        %endfor
 
    %endfor
 

	
 
</%def>
 

	
 
## generate inline comments and the main ones
 
<%def name="generate_comments(include_pr=False)">
 
<div class="comments">
 
    <div id="inline-comments-container">
 
    ## generate inlines for this changeset
 
     ${inlines()}
 
    </div>
 

	
 
    %for co in c.comments:
 
        <div id="comment-tr-${co.comment_id}">
 
          ## only render comments that are not from pull request, or from
 
          ## pull request and a status change
 
          %if not co.pull_request or (co.pull_request and co.status_change) or include_pr:
 
          ${comment_block(co)}
 
          %endif
 
        </div>
 
    %endfor
 
</div>
 
</%def>
 

	
 
## MAIN COMMENT FORM
 
<%def name="comments(post_url, cur_status, is_pr=False, change_status=True)">
 

	
 
<div class="comments">
 
    %if c.rhodecode_user.username != 'default':
 
    %if c.authuser.username != 'default':
 
    <div class="comment-form ac">
 
        ${h.form(post_url)}
 
        <div id="edit-container" class="clearfix">
 
            <div class="comment-help">
 
                ${(_('Comments parsed using %s syntax with %s support.') % (('<a href="%s">RST</a>' % h.url('rst_help')),
 
                  '<span style="color:#003367" class="tooltip" title="%s">@mention</span>' %
 
                  _('Use @username inside this text to send notification to this RhodeCode user')))|n}
 
              %if change_status:
 
                | <a id="show_changeset_link" onClick="change_status_show();">
 
                  %if is_pr:
 
                    ${_('Vote for pull request status')}
 
                  %else:
 
                    ${_('Change changeset status')}
 
                  %endif
 
                  </a>
 
                  <input id="show_changeset_status_box" type="checkbox" name="change_changeset_status" style="display: none;" />
 
              %endif
 
              <div id="preview-btn" class="preview-btn btn btn-mini">${_('Preview')}</div>
 
            </div>
 
            %if change_status:
 
            <div id="status_block_container" class="status-block" style="display:none">
 
                %for status,lbl in c.changeset_statuses:
 
                    <div class="">
 
                        <img src="${h.url('/images/icons/flag_status_%s.png' % status)}" />
 
                        <input ${'checked="checked"' if status == cur_status else ''}" type="radio" class="status_change_radio" name="changeset_status" id="${status}" value="${status}">
 
                        <label for="${status}">${lbl}</label>
 
                    </div>
 
                %endfor
 
                %if is_pr and change_status:
 
                <input id="save_close" type="checkbox" name="save_close" disabled="${'1' if cur_status in ['not_reviewed','under_review'] else ''}">
 
                <label id="save_close_label" for="save_close" class="${'disabled' if cur_status in ['not_reviewed','under_review'] else ''}">${_("Close (when approved or rejected)")}</label>
 
                %endif
 
            </div>
 
            %endif
 
            <div class="mentions-container" id="mentions_container"></div>
 
             ${h.textarea('text', class_="comment-block-ta")}
 
        </div>
 

	
 
        <div id="preview-container" class="clearfix" style="display:none">
 
           <div class="comment-help">
 
                ${_('Comment preview')}
 
              <div id="edit-btn" class="edit-btn btn btn-mini">${_('Edit')}</div>
 
            </div>
 
            <div id="preview-box" class="preview-box"></div>
 
        </div>
 

	
 
        <div class="comment-button">
 
        ${h.submit('save', _('Comment'), class_="btn")}
kallithea/templates/data_table/_dt_elements.html
Show inline comments
 
@@ -54,106 +54,106 @@
 
    ##NAME
 
    %if admin:
 
        <a href="${h.url('edit_repo',repo_name=name)}">
 
    %else:
 
        <a href="${h.url('summary_home',repo_name=name)}">
 
    %endif
 

	
 
    ##TYPE OF REPO
 
    %if h.is_hg(rtype):
 
        <span title="${_('Mercurial repository')}"><i class="icon-hg" style="color: #316293; font-size: 14px;"></i></span>
 
    %elif h.is_git(rtype):
 
        <span title="${_('Git repository')}"><i class="icon-git" style="color: #e85634; font-size: 14px;"></i></span>
 
    %endif
 

	
 
    ##PRIVATE/PUBLIC
 
    %if private and c.visual.show_private_icon:
 
      <i class="icon-lock" style="color: #e85634; font-size: 16px; vertical-align: -2px; margin: 0px 1px 0px 3px" title="${_('Private repository')}"></i>
 
    %elif not private and c.visual.show_public_icon:
 
      <i class="icon-unlock-alt" style="color: #999999; font-size: 16px; vertical-align: -2px; margin: 0px 1px 0px 3px" title="${_('Public repository')}"></i>
 
    %else:
 
      <span style="margin: 0px 8px 0px 8px"></span>
 
    %endif
 
    ${get_name(name)}
 
    </a>
 
    %if fork_of:
 
      <a href="${h.url('summary_home',repo_name=fork_of.repo_name)}"><i class="icon-code-fork"></i></a>
 
    %endif
 
    %if rstate == 'repo_state_pending':
 
      <i class="icon-cogs" style="color: #036185;" title="${_('Repository creating in progress...')}"></i>
 
    %endif
 
  </div>
 
</%def>
 

	
 
<%def name="last_change(last_change)">
 
  <span class="tooltip" date="${last_change}" title="${h.tooltip(h.fmt_date(last_change))}">${h.age(last_change)}</span>
 
</%def>
 

	
 
<%def name="revision(name,rev,tip,author,last_msg)">
 
  <div>
 
  %if rev >= 0:
 
      <pre><a title="${h.tooltip('%s:\n\n%s' % (author,last_msg))}" class="tooltip" href="${h.url('changeset_home',repo_name=name,revision=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a></pre>
 
  %else:
 
      ${_('No changesets yet')}
 
  %endif
 
  </div>
 
</%def>
 

	
 
<%def name="rss(name)">
 
  %if c.rhodecode_user.username != 'default':
 
    <a title="${_('Subscribe to %s rss feed')% name}" href="${h.url('rss_feed_home',repo_name=name,api_key=c.rhodecode_user.api_key)}"><i class="icon-rss-sign" style="color: #fa9b39"></i></a>
 
  %if c.authuser.username != 'default':
 
    <a title="${_('Subscribe to %s rss feed')% name}" href="${h.url('rss_feed_home',repo_name=name,api_key=c.authuser.api_key)}"><i class="icon-rss-sign" style="color: #fa9b39"></i></a>
 
  %else:
 
    <a title="${_('Subscribe to %s rss feed')% name}" href="${h.url('rss_feed_home',repo_name=name)}"><i class="icon-rss-sign" style="color: #fa9b39"></i></a>
 
  %endif
 
</%def>
 

	
 
<%def name="atom(name)">
 
  %if c.rhodecode_user.username != 'default':
 
    <a title="${_('Subscribe to %s atom feed')% name}" href="${h.url('atom_feed_home',repo_name=name,api_key=c.rhodecode_user.api_key)}"><i class="icon-rss-sign"  style="color: #fa9b39"></i></a>
 
  %if c.authuser.username != 'default':
 
    <a title="${_('Subscribe to %s atom feed')% name}" href="${h.url('atom_feed_home',repo_name=name,api_key=c.authuser.api_key)}"><i class="icon-rss-sign"  style="color: #fa9b39"></i></a>
 
  %else:
 
    <a title="${_('Subscribe to %s atom feed')% name}" href="${h.url('atom_feed_home',repo_name=name)}"><i class="icon-rss-sign"  style="color: #fa9b39"></i></a>
 
  %endif
 
</%def>
 

	
 
<%def name="user_gravatar(email, size=24)">
 
    <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(email, size)}"/> </div>
 
</%def>
 

	
 
<%def name="repo_actions(repo_name, super_user=True)">
 
  <div>
 
    <div style="float:left; margin-right:5px;" class="grid_edit">
 
      <a href="${h.url('edit_repo',repo_name=repo_name)}" title="${_('edit')}">
 
        <i class="icon-pencil"></i> ${h.submit('edit_%s' % repo_name,_('edit'),class_="action_button")}
 
      </a>
 
    </div>
 
    <div style="float:left" class="grid_delete">
 
      ${h.form(h.url('repo', repo_name=repo_name),method='delete')}
 
        <i class="icon-remove-sign" style="color:#FF4444"></i>
 
        ${h.submit('remove_%s' % repo_name,_('delete'),class_="action_button",
 
        onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")}
 
      ${h.end_form()}
 
    </div>
 
  </div>
 
</%def>
 

	
 
<%def name="repo_state(repo_state)">
 
  <div>
 
    %if repo_state == 'repo_state_pending':
 
        <div class="btn btn-mini btn-info disabled">${_('Creating')}</div>
 
    %elif repo_state == 'repo_state_created':
 
        <div class="btn btn-mini btn-success disabled">${_('Created')}</div>
 
    %else:
 
        <div class="btn btn-mini btn-danger disabled" title="${repo_state}">invalid</div>
 
    %endif
 
  </div>
 
</%def>
 

	
 
<%def name="user_actions(user_id, username)">
 
 <div style="float:left" class="grid_edit">
 
   <a href="${h.url('edit_user',id=user_id)}" title="${_('edit')}">
 
     <i class="icon-pencil"></i> ${h.submit('edit_%s' % username,_('edit'),class_="action_button")}
 
   </a>
 
 </div>
 
 <div style="float:left" class="grid_delete">
 
  ${h.form(h.url('delete_user', id=user_id),method='delete')}
 
    <i class="icon-remove-sign" style="color:#FF4444"></i>
 
    ${h.submit('remove_',_('delete'),id="remove_user_%s" % user_id, class_="action_button",
kallithea/templates/index_base.html
Show inline comments
 
<%page args="parent,group_name=''" />
 
    <div class="box">
 
        <!-- box / title -->
 
        <div class="title">
 
            <h5>
 
            <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/> ${parent.breadcrumbs()} <span id="repo_count">0</span> ${_('repositories')}
 
            </h5>
 
            %if c.rhodecode_user.username != 'default':
 
            %if c.authuser.username != 'default':
 
              <ul class="links">
 
                <li>
 
                <%
 
                    gr_name = c.group.group_name if c.group else None
 
                    # create repositories with write permission on group is set to true
 
                    create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
 
                    group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'can write into group index page')
 
                    group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
 
                %>
 
                %if h.HasPermissionAny('hg.admin','hg.create.repository')() or (group_admin or (group_write and create_on_write)):
 
                  %if c.group:
 
                        <a href="${h.url('new_repo',parent_group=c.group.group_id)}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_('Add Repository')}</a>
 
                        %if h.HasPermissionAny('hg.admin')() or h.HasRepoGroupPermissionAny('group.admin')(c.group.group_name):
 
                            <a href="${h.url('new_repos_group', parent_group=c.group.group_id)}" class="btn btn-small"><i class="icon-plus"></i> ${_(u'Add Repository Group')}</a>
 
                        %endif
 
                  %else:
 
                    <a href="${h.url('new_repo')}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_('Add Repository')}</a>
 
                    %if h.HasPermissionAny('hg.admin')():
 
                        <a href="${h.url('new_repos_group')}" class="btn btn-small"><i class="icon-plus"></i> ${_(u'Add Repository Group')}</a>
 
                    %endif
 
                  %endif
 
                %endif
 
                %if c.group and h.HasRepoGroupPermissionAny('group.admin')(c.group.group_name):
 
                    <a href="${h.url('edit_repo_group',group_name=c.group.group_name)}" title="${_('You have admin right to this group, and can edit it')}" class="btn btn-small"><i class="icon-pencil"></i> ${_('Edit Repository Group')}</a>
 
                %endif
 
                </li>
 
              </ul>
 
            %endif
 
        </div>
 
        <!-- end box / title -->
 
        <div class="table">
 
           % if c.groups:
 
            <div id='groups_list_wrap' class="yui-skin-sam">
 
              <table id="groups_list">
 
                  <thead>
 
                      <tr>
 
                          <th class="left"><a href="#">${_('Group Name')}</a></th>
 
                          <th class="left"><a href="#">${_('Description')}</a></th>
 
                          ##<th class="left"><a href="#">${_('Number of Repositories')}</a></th>
 
                      </tr>
 
                  </thead>
 

	
 
                  ## REPO GROUPS
 
                  % for gr in c.groups:
 
                    <tr>
 
                        <td>
 
                            <div style="white-space: nowrap">
 
                                <a href="${url('repos_group_home',group_name=gr.group_name)}"><i class="icon-folder-close"></i> ${gr.name}</a>
kallithea/templates/journal/journal.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 
<%def name="title()">
 
    ${_('Journal')}
 
    %if c.rhodecode_name:
 
        &middot; ${c.rhodecode_name}
 
    %endif
 
</%def>
 
<%def name="breadcrumbs()">
 
    <h5>
 
    <form id="filter_form">
 
    <input class="q_filter_box ${'' if c.search_term else 'initial'}" id="j_filter" size="15" type="text" name="filter" value="${c.search_term or _('quick filter...')}"/>
 
    <span class="tooltip" title="${h.tooltip(h.journal_filter_help())}">?</span>
 
    <input type='submit' value="${_('filter')}" class="btn btn-small" style="padding:0px 2px 0px 2px;margin:0px"/>
 
    ${_('journal')} - ${ungettext('%s entry', '%s entries', c.journal_pager.item_count) % (c.journal_pager.item_count)}
 
    </form>
 
    ${h.end_form()}
 
    </h5>
 
</%def>
 
<%def name="page_nav()">
 
    ${self.menu('journal')}
 
</%def>
 
<%def name="head_extra()">
 
<link href="${h.url('journal_atom', api_key=c.rhodecode_user.api_key)}" rel="alternate" title="${_('ATOM journal feed')}" type="application/atom+xml" />
 
<link href="${h.url('journal_rss', api_key=c.rhodecode_user.api_key)}" rel="alternate" title="${_('RSS journal feed')}" type="application/rss+xml" />
 
<link href="${h.url('journal_atom', api_key=c.authuser.api_key)}" rel="alternate" title="${_('ATOM journal feed')}" type="application/atom+xml" />
 
<link href="${h.url('journal_rss', api_key=c.authuser.api_key)}" rel="alternate" title="${_('RSS journal feed')}" type="application/rss+xml" />
 
</%def>
 
<%def name="main()">
 

	
 
    <div class="box box-left">
 
        <!-- box / title -->
 
        <div class="title">
 
         ${self.breadcrumbs()}
 
         <ul class="links icon-only-links">
 
           <li>
 
             <span><a id="refresh" href="${h.url('journal')}"><i class="icon-refresh"></i></a></span>
 
           </li>
 
           <li>
 
             <span><a href="${h.url('journal_atom', api_key=c.rhodecode_user.api_key)}"><i class="icon-rss-sign"></i></a></span>
 
             <span><a href="${h.url('journal_atom', api_key=c.authuser.api_key)}"><i class="icon-rss-sign"></i></a></span>
 
           </li>
 
         </ul>
 
        </div>
 
        <div id="journal">${c.journal_data}</div>
 
    </div>
 
    <div class="box box-right">
 
        <!-- box / title -->
 

	
 
        <div class="title">
 
            <h5>
 
            <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value="" style="display: none"/>
 
            <input class="q_filter_box" id="q_filter_watched" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value="" style="display: none"/>
 
            </h5>
 
            <ul class="links nav nav-tabs">
 
                <li class="active" id="show_watched_li">
 
                    <a id="show_watched" href="#watched"><i class="icon-eye-open"></i> ${_('Watched')}</a>
 
                </li>
 
                <li id="show_my_li">
 
                    <a id="show_my" href="#my"><i class="icon-archive"></i> ${_('My repos')}</a>
 
               </li>
 
            </ul>
 
        </div>
 

	
 
        <!-- end box / title -->
 
        <div id="my_container" style="display:none">
 
            <div class="table-grid table yui-skin-sam" id="repos_list_wrap"></div>
 
            <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
 
        </div>
 

	
 
        <div id="watched_container">
 
            <div class="table-grid table yui-skin-sam" id="watched_repos_list_wrap"></div>
 
            <div id="watched-user-paginator" style="padding: 0px 0px 0px 20px"></div>
 
        </div>
 
    </div>
 

	
 
    <script type="text/javascript">
 

	
 
    YUE.on('j_filter','click',function(){
 
        var jfilter = YUD.get('j_filter');
 
        if(YUD.hasClass(jfilter, 'initial')){
 
            jfilter.value = '';
 
        }
 
    });
 
    var fix_j_filter_width = function(len){
 
        YUD.setStyle(YUD.get('j_filter'),'width',Math.max(80, len*6.50)+'px');
 
    }
 
    YUE.on('j_filter','keyup',function(){
 
        fix_j_filter_width(YUD.get('j_filter').value.length);
kallithea/templates/pullrequests/pullrequest_show.html
Show inline comments
 
@@ -70,109 +70,109 @@ ${self.repo_context_bar('showpullrequest
 
          <div class="input">
 
              <div>
 

	
 
              ## branch link is only valid if it is a branch
 
              <span class="spantag"><a href="${h.url('summary_home', repo_name=c.pull_request.org_repo.repo_name, anchor=c.pull_request.org_ref_parts[1])}">${c.pull_request.org_ref_parts[0]}: ${c.pull_request.org_ref_parts[1]}</a></span>
 
              <span>
 
               %if h.is_hg(c.pull_request.org_repo):
 
                 | ${_('Pull changes')} <span style="font-family: monospace">hg pull -r ${h.short_id(c.cs_ranges[-1].raw_id)} <a href="${h.url('summary_home', repo_name=c.pull_request.org_repo.repo_name)}">${c.pull_request.org_repo.clone_url()}</a></span>
 
               %elif h.is_git(c.pull_request.org_repo):
 
                 | ${_('Pull changes')} <span style="font-family: monospace">git pull <a href="${h.url('summary_home', repo_name=c.pull_request.org_repo.repo_name)}">${c.pull_request.org_repo.clone_url()}</a> ${c.pull_request.org_ref_parts[1]} </span>
 
               %endif
 
              </div>
 
          </div>
 
         </div>
 
         <div class="field">
 
          <div class="label-summary">
 
              <label>${_('Description')}:</label>
 
          </div>
 
          <div class="input">
 
              <div style="white-space:pre-wrap">${h.urlify_commit(c.pull_request.description, c.repo_name)}</div>
 
          </div>
 
         </div>
 
         <div class="field">
 
          <div class="label-summary">
 
              <label>${_('Created on')}:</label>
 
          </div>
 
          <div class="input">
 
              <div>${h.fmt_date(c.pull_request.created_on)}</div>
 
          </div>
 
         </div>
 
      </div>
 
    </div>
 
    ## REVIEWERS
 
    <div style="float:left; border-left:1px dashed #eee">
 
       <div class="pr-details-title">${_('Pull request reviewers')}</div>
 
        <div id="reviewers" style="padding:0px 0px 5px 10px">
 
          ## members goes here !
 
          <div>
 
            <ul id="review_members" class="group_members">
 
            %for member,status in c.pull_request_reviewers:
 
              <li id="reviewer_${member.user_id}">
 
                <div class="reviewers_member">
 
                    <div class="reviewer_status tooltip" title="${h.tooltip(h.changeset_status_lbl(status[0][1].status if status else 'not_reviewed'))}">
 
                      <img src="${h.url(str('/images/icons/flag_status_%s.png' % (status[0][1].status if status else 'not_reviewed')))}"/>
 
                    </div>
 
                  <div class="reviewer_gravatar gravatar"><img alt="gravatar" src="${h.gravatar_url(member.email,14)}"/> </div>
 
                  <div style="float:left;">${member.full_name} (${_('owner') if c.pull_request.user_id == member.user_id else _('reviewer')})</div>
 
                  <input type="hidden" value="${member.user_id}" name="review_members" />
 
                  %if not c.pull_request.is_closed() and (h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or c.pull_request.user_id == c.rhodecode_user.user_id):
 
                  %if not c.pull_request.is_closed() and (h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or c.pull_request.user_id == c.authuser.user_id):
 
                  <div class="reviewer_member_remove action_button" onclick="removeReviewMember(${member.user_id})">
 
                      <i class="icon-remove-sign" style="color: #FF4444;"></i>
 
                  </div>
 
                  %endif
 
                </div>
 
              </li>
 
            %endfor
 
            </ul>
 
          </div>
 
          %if not c.pull_request.is_closed():
 
          <div class='ac'>
 
            %if h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or c.pull_request.author.user_id == c.rhodecode_user.user_id:
 
            %if h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or c.pull_request.author.user_id == c.authuser.user_id:
 
            <div class="reviewer_ac">
 
               ${h.text('user', class_='yui-ac-input')}
 
               <span class="help-block">${_('Add or remove reviewer to this pull request.')}</span>
 
               <div id="reviewers_container"></div>
 
            </div>
 
            <div style="padding:0px 10px">
 
             <span id="update_pull_request" class="btn btn-mini">${_('Save Changes')}</span>
 
            </div>
 
            %endif
 
          </div>
 
          %endif
 
        </div>
 
       </div>
 

	
 
    <div style="overflow: auto; clear: both">
 
      ##DIFF
 
      <div class="table" style="float:left;clear:none">
 
          <div id="body" class="diffblock">
 
              <div style="white-space:pre-wrap;padding:5px">${_('Compare view')}</div>
 
          </div>
 
          <div id="changeset_compare_view_content">
 
              ##CS
 
              <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${ungettext('Showing %s commit','Showing %s commits', len(c.cs_ranges)) % len(c.cs_ranges)}</div>
 
              <%include file="/compare/compare_cs.html" />
 

	
 
              ## FILES
 
              <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
 

	
 
              % if c.limited_diff:
 
                  ${ungettext('%s file changed', '%s files changed', len(c.files)) % len(c.files)}
 
              % else:
 
                  ${ungettext('%s file changed with %s insertions and %s deletions','%s files changed with %s insertions and %s deletions', len(c.files)) % (len(c.files),c.lines_added,c.lines_deleted)}:
 
              %endif
 

	
 
              </div>
 
              <div class="cs_files">
 
                %if not c.files:
 
                   <span class="empty_data">${_('No files')}</span>
 
                %endif
 
                %for fid, change, f, stat in c.files:
 
                    <div class="cs_${change}">
 
                      <div class="node">${h.link_to(h.safe_unicode(f),h.url.current(anchor=fid))}</div>
 
                      <div class="changes">${h.fancy_file_stats(stat)}</div>
 
                    </div>
 
                %endfor
 
              </div>
 
              % if c.limited_diff:
 
                <h5>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}" onclick="return confirm('${_("Showing a huge diff might take some time and resources")}')">${_('Show full diff')}</a></h5>
kallithea/templates/pullrequests/pullrequest_show_all.html
Show inline comments
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('%s Pull Requests') % c.repo_name}
 
    %if c.rhodecode_name:
 
        &middot; ${c.rhodecode_name}
 
    %endif
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
%if c.from_:
 
    ${_('Pull requests from %s') % c.repo_name}
 
%else:
 
    ${_('Pull requests to %s') % c.repo_name}
 
%endif
 
</%def>
 

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

	
 
<%def name="main()">
 
${self.repo_context_bar('showpullrequest')}
 

	
 
<div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
        <ul class="links">
 
          <li>
 
             %if c.rhodecode_user.username != 'default':
 
             %if c.authuser.username != 'default':
 
              <span>
 
                  <a id="open_new_pr" class="btn btn-small btn-success" href="${h.url('pullrequest_home',repo_name=c.repo_name)}"><i class="icon-plus"></i> ${_('Open new pull request')}</a>
 
              </span>
 
             %endif
 
              <span>
 
                %if c.from_:
 
                    <a class="btn btn-small" href="${h.url('pullrequest_show_all',repo_name=c.repo_name,closed=c.closed)}"><i class="icon-loop-2"></i> ${_('Show pull requests to %s') % c.repo_name}</a>
 
                %else:
 
                    <a class="btn btn-small" href="${h.url('pullrequest_show_all',repo_name=c.repo_name,closed=c.closed,from_=1)}"><i class="icon-loop-2"></i> ${_('Show pull requests from %s') % c.repo_name}</a>
 
                %endif
 
              </span>
 
          </li>
 
        </ul>
 
    </div>
 

	
 
    <div style="margin: 0 20px">
 
        <div>
 
        %if c.closed:
 
            ${h.link_to(_('Hide closed pull requests'), h.url('pullrequest_show_all',repo_name=c.repo_name,from_=c.from_))}
 
        %else:
 
            ${h.link_to(_('Show closed pull requests too'), h.url('pullrequest_show_all',repo_name=c.repo_name,from_=c.from_,closed=1))}
 
        %endif
 
        </div>
 
    </div>
 

	
 
    ${c.pullrequest_data}
 

	
 
</div>
 
</%def>
kallithea/templates/summary/statistics.html
Show inline comments
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('%s Statistics') % c.repo_name}
 
    %if c.rhodecode_name:
 
        &middot; ${c.rhodecode_name}
 
    %endif
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${_('Statistics')}
 
</%def>
 

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

	
 
<%def name="head_extra()">
 
<link href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=c.rhodecode_user.api_key)}" rel="alternate" title="${_('%s ATOM feed') % c.repo_name}" type="application/atom+xml" />
 
<link href="${h.url('rss_feed_home',repo_name=c.db_repo.repo_name,api_key=c.rhodecode_user.api_key)}" rel="alternate" title="${_('%s RSS feed') % c.repo_name}" type="application/rss+xml" />
 
<link href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}" rel="alternate" title="${_('%s ATOM feed') % c.repo_name}" type="application/atom+xml" />
 
<link href="${h.url('rss_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}" rel="alternate" title="${_('%s RSS feed') % c.repo_name}" type="application/rss+xml" />
 
</%def>
 

	
 
<%def name="main()">
 
${self.repo_context_bar('summary')}
 
    <%
 
    summary = lambda n:{False:'summary-short'}.get(n)
 
    %>
 
    <div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
    </div>
 

	
 
    <div class="graph">
 
         <div style="padding:0 10px 10px 17px;">
 
         %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_="btn btn-mini")}
 
           %endif
 
        %else:
 
            ${_('Stats gathered: ')} ${c.stats_percentage}%
 
        %endif
 
        </div>
 
        <div id="commit_history" style="width:450px;height:300px;float:left"></div>
 
        <div style="clear: both;height: 10px"></div>
 
        <div id="overview" style="width:450px;height:100px;float:left"></div>
 

	
 
        <div id="legend_data" style="clear:both;margin-top:10px;">
 
            <div id="legend_container"></div>
 
            <div id="legend_choices">
 
                <table id="legend_choices_tables" class="noborder" style="font-size:smaller;color:#545454"></table>
 
            </div>
 
        </div>
 
    </div>
 
</div>
 

	
 
<script type="text/javascript">
 
var data = ${c.trending_languages|n};
 
var total = 0;
 
var no_data = true;
 
var tbl = document.createElement('table');
 
tbl.setAttribute('class','trending_language_tbl');
 
var cnt = 0;
 
for (var i=0;i<data.length;i++){
 
    total+= data[i][1].count;
 
}
 
for (var i=0;i<data.length;i++){
kallithea/templates/summary/summary.html
Show inline comments
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('%s Summary') % c.repo_name}
 
    %if c.rhodecode_name:
 
        &middot; ${c.rhodecode_name}
 
    %endif
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${_('Summary')}
 

	
 
    ## locking icon
 
    %if c.db_repo.enable_locking:
 
     %if c.db_repo.locked[0]:
 
       <span class="locking_locked tooltip" title="${_('Repository locked by %s') % h.person_by_id(c.db_repo.locked[0])}"></span>
 
     %else:
 
       <span class="locking_unlocked tooltip" title="${_('Repository unlocked')}"></span>
 
     %endif
 
    %endif
 

	
 
    ##FORK
 
    %if c.db_repo.fork:
 
    <span>
 
        - <i class="icon-code-fork"></i> ${_('Fork of')} "<a href="${h.url('summary_home',repo_name=c.db_repo.fork.repo_name)}">${c.db_repo.fork.repo_name}</a>"
 
    </span>
 
    %endif
 

	
 
    ##REMOTE
 
    %if c.db_repo.clone_uri:
 
    <span>
 
       - <i class="icon-code-fork"></i> ${_('Clone from')} "<a href="${h.url(str(h.hide_credentials(c.db_repo.clone_uri)))}">${h.hide_credentials(c.db_repo.clone_uri)}</a>"
 
    <span>
 
    %endif
 
</%def>
 

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

	
 
<%def name="head_extra()">
 
<link href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=c.rhodecode_user.api_key)}" rel="alternate" title="${_('%s ATOM feed') % c.repo_name}" type="application/atom+xml" />
 
<link href="${h.url('rss_feed_home',repo_name=c.db_repo.repo_name,api_key=c.rhodecode_user.api_key)}" rel="alternate" title="${_('%s RSS feed') % c.repo_name}" type="application/rss+xml" />
 
<link href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}" rel="alternate" title="${_('%s ATOM feed') % c.repo_name}" type="application/atom+xml" />
 
<link href="${h.url('rss_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}" rel="alternate" title="${_('%s RSS feed') % c.repo_name}" type="application/rss+xml" />
 

	
 
<script>
 
redirect_hash_branch = function(){
 
    var branch = window.location.hash.replace(/^#(.*)/, '$1');
 
    if (branch){
 
        window.location = "${h.url('changelog_home',repo_name=c.repo_name,branch='__BRANCH__')}"
 
            .replace('__BRANCH__',branch);
 
    }
 
}
 
redirect_hash_branch();
 
window.onhashchange = function() {
 
    redirect_hash_branch();
 
};
 
</script>
 

	
 
</%def>
 

	
 
<%def name="main()">
 
${self.repo_context_bar('summary')}
 
<%
 
summary = lambda n:{False:'summary-short'}.get(n)
 
%>
 
<div class="box">
 
    <!-- 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>${_('Clone url')}:</label>
 
                </div>
 
                <div class="input ${summary(c.show_stats)}">
 
                  <input style="width:80%" type="text" id="clone_url" readonly="readonly" value="${c.clone_repo_url}"/>
 
                  <input style="display:none;width:80%" type="text" id="clone_url_id" readonly="readonly" value="${c.clone_repo_url_id}"/>
 
                  <div style="display:none" id="clone_by_name" class="btn btn-small clone">${_('Show by Name')}</div>
 
                  <div id="clone_by_id" class="btn btn-small clone">${_('Show by ID')}</div>
 
                </div>
 
            </div>
 

	
 
            <div class="field">
 
              <div class="label-summary">
 
                  <label>${_('Description')}:</label>
 
              </div>
 
                 %if c.visual.stylify_metatags:
 
                   <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(h.desc_stylize(c.db_repo.description))}</div>
 
@@ -113,106 +113,106 @@ summary = lambda n:{False:'summary-short
 
            <div class="field">
 
              <div class="label-summary">
 
                  <label>${_('Download')}:</label>
 
              </div>
 
              <div class="input ${summary(c.show_stats)}">
 
                %if len(c.db_repo_scm_instance.revisions) == 0:
 
                  ${_('There are no downloads yet')}
 
                %elif not c.enable_downloads:
 
                  ${_('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, anchor='repo_enable_downloads'),class_="btn btn-mini")}
 
                    %endif
 
                %else:
 
                    <span id="${'zip_link'}">
 
                        <a class="btn btn-small" href="${h.url('files_archive_home',repo_name=c.db_repo.repo_name,fname='tip.zip')}"><i class="icon-archive"></i> ${_('Download as zip')}</a>
 
                    </span>
 
                    ${h.hidden('download_options')}
 
                    <span style="vertical-align: bottom">
 
                      <input id="archive_subrepos" type="checkbox" name="subrepos" />
 
                      <label for="archive_subrepos" class="tooltip" title="${h.tooltip(_('Check this to download archive with subrepos'))}" >${_('with subrepos')}</label>
 
                    </span>
 
                %endif
 
              </div>
 
            </div>
 
        </div>
 
        <div id="summary-menu-stats">
 
          <ul>
 
            <li>
 
               <a title="${_('Owner')} ${c.db_repo.user.email}">
 
                <i class="icon-user"></i> ${c.db_repo.user.username}
 
                  <div class="gravatar" style="float: right; margin: 0px 0px 0px 0px" title="${c.db_repo.user.name} ${c.db_repo.user.lastname}">
 
                     <img alt="gravatar" src="${h.gravatar_url(c.db_repo.user.email, 18)}"/>
 
                  </div>
 
              </a>
 
            </li>
 
            <li>
 
               <a title="${_('Followers')}" href="${h.url('repo_followers_home',repo_name=c.repo_name)}">
 
                <i class="icon-heart"></i> ${_('Followers')}
 
                <span class="stats-bullet" id="current_followers_count">${c.repository_followers}</span>
 
              </a>
 
            </li>
 
            <li>
 
              <a title="${_('Forks')}" href="${h.url('repo_forks_home',repo_name=c.repo_name)}">
 
                <i class="icon-code-fork"></i> ${_('Forks')}
 
                <span class="stats-bullet">${c.repository_forks}</span>
 
              </a>
 
            </li>
 

	
 
            %if c.rhodecode_user.username != 'default':
 
            %if c.authuser.username != 'default':
 
            <li class="repo_size">
 
              <a href="#" onclick="javascript:showRepoSize('repo_size_2','${c.db_repo.repo_name}','${str(h.get_token())}')"><i class="icon-archive"></i> ${_('Repository Size')}</a>
 
              <span  class="stats-bullet" id="repo_size_2"></span>
 
            </li>
 
            %endif
 

	
 
            <li>
 
            %if c.rhodecode_user.username != 'default':
 
              <a href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=c.rhodecode_user.api_key)}"><i class="icon-rss-sign"></i> ${_('Feed')}</a>
 
            %if c.authuser.username != 'default':
 
              <a href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}"><i class="icon-rss-sign"></i> ${_('Feed')}</a>
 
            %else:
 
              <a href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name)}"><i class="icon-rss-sign"></i> ${_('Feed')}</a>
 
            %endif
 
            </li>
 

	
 
            %if c.show_stats:
 
            <li>
 
              <a title="${_('Statistics')}" href="${h.url('repo_stats_home',repo_name=c.repo_name)}">
 
                <i class="icon-bar-chart"></i> ${_('Statistics')}
 
              </a>
 
            </li>
 
            %endif
 
          </ul>
 
        </div>
 
    </div>
 
</div>
 

	
 

	
 
<div class="box">
 
    <div class="title">
 
        <div class="breadcrumbs">
 
        %if c.repo_changesets:
 
            ${h.link_to(_('Latest changes'),h.url('changelog_home',repo_name=c.repo_name))}
 
        %else:
 
            ${_('Quick start')}
 
         %endif
 
        </div>
 
    </div>
 
    <div class="table">
 
        <div id="shortlog_data">
 
            <%include file='../changelog/changelog_summary_data.html'/>
 
        </div>
 
    </div>
 
</div>
 

	
 
%if c.readme_data:
 
<div id="readme" class="anchor">
 
<div class="box" style="background-color: #FAFAFA">
 
    <div class="title" title="${_('Readme file from revision %s:%s') % (c.db_repo.landing_rev[0], c.db_repo.landing_rev[1])}">
 
        <div class="breadcrumbs">
 
            <a href="${h.url('files_home',repo_name=c.repo_name,revision='tip',f_path=c.readme_file)}">${c.readme_file}</a>
 
        </div>
 
    </div>
 
    <div class="readme">
 
      <div class="readme_box">
 
        ${c.readme_data|n}
 
      </div>
 
    </div>
kallithea/tests/__init__.py
Show inline comments
 
@@ -153,65 +153,65 @@ def get_new_dir(title):
 
    from kallithea.tests.vcs.utils import get_normalized_path
 
    name = TEST_REPO_PREFIX
 
    if title:
 
        name = '-'.join((name, title))
 
    hex = hashlib.sha1(str(time.time())).hexdigest()
 
    name = '-'.join((name, hex))
 
    path = os.path.join(TEST_DIR, name)
 
    return get_normalized_path(path)
 

	
 

	
 
def init_stack(config=None):
 
    if not config:
 
        config = pylons.test.pylonsapp.config
 
    url._push_object(URLGenerator(config['routes.map'], environ))
 
    pylons.app_globals._push_object(config['pylons.app_globals'])
 
    pylons.config._push_object(config)
 
    pylons.tmpl_context._push_object(ContextObj())
 
    # Initialize a translator for tests that utilize i18n
 
    translator = _get_translator(pylons.config.get('lang'))
 
    pylons.translator._push_object(translator)
 

	
 

	
 
class BaseTestCase(unittest.TestCase):
 
    def __init__(self, *args, **kwargs):
 
        self.wsgiapp = pylons.test.pylonsapp
 
        init_stack(self.wsgiapp.config)
 
        unittest.TestCase.__init__(self, *args, **kwargs)
 

	
 

	
 
class TestController(BaseTestCase):
 

	
 
    def __init__(self, *args, **kwargs):
 
        BaseTestCase.__init__(self, *args, **kwargs)
 
        self.app = TestApp(self.wsgiapp)
 
        self.maxDiff = None
 
        self.index_location = config['app_conf']['index_dir']
 

	
 
    def log_user(self, username=TEST_USER_ADMIN_LOGIN,
 
                 password=TEST_USER_ADMIN_PASS):
 
        self._logged_username = username
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': username,
 
                                  'password': password})
 

	
 
        if 'invalid user name' in response.body:
 
            self.fail('could not login using %s %s' % (username, password))
 

	
 
        self.assertEqual(response.status, '302 Found')
 
        ses = response.session['rhodecode_user']
 
        ses = response.session['authuser']
 
        self.assertEqual(ses.get('username'), username)
 
        response = response.follow()
 
        self.assertEqual(ses.get('is_authenticated'), True)
 

	
 
        return response.session['rhodecode_user']
 
        return response.session['authuser']
 

	
 
    def _get_logged_user(self):
 
        return User.get_by_username(self._logged_username)
 

	
 
    def checkSessionFlash(self, response, msg):
 
        self.assertTrue('flash' in response.session,
 
                        msg='Response session have no flash key' % response.session)
 
        if not msg in response.session['flash'][0][1]:
 
            msg = u'msg `%s` not found in session flash: got `%s` instead' % (
 
                      msg, response.session['flash'][0][1])
 
            self.fail(safe_str(msg))
kallithea/tests/functional/test_login.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
from __future__ import with_statement
 
import mock
 
from kallithea.tests import *
 
from kallithea.tests.fixture import Fixture
 
from kallithea.lib.utils2 import generate_api_key
 
from kallithea.lib.auth import check_password
 
from kallithea.lib import helpers as h
 
from kallithea.model.api_key import ApiKeyModel
 
from kallithea.model import validators
 
from kallithea.model.db import User, Notification
 
from kallithea.model.meta import Session
 

	
 
fixture = Fixture()
 

	
 

	
 
class TestLoginController(TestController):
 

	
 
    def tearDown(self):
 
        for n in Notification.query().all():
 
            Session().delete(n)
 

	
 
        Session().commit()
 
        self.assertEqual(Notification.query().all(), [])
 

	
 
    def test_index(self):
 
        response = self.app.get(url(controller='login', action='index'))
 
        self.assertEqual(response.status, '200 OK')
 
        # Test response...
 

	
 
    def test_login_admin_ok(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': 'test_admin',
 
                                  'password': 'test12'})
 
        self.assertEqual(response.status, '302 Found')
 
        self.assertEqual(response.session['rhodecode_user'].get('username'),
 
        self.assertEqual(response.session['authuser'].get('username'),
 
                         'test_admin')
 
        response = response.follow()
 
        response.mustcontain('/%s' % HG_REPO)
 

	
 
    def test_login_regular_ok(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': 'test_regular',
 
                                  'password': 'test12'})
 

	
 
        self.assertEqual(response.status, '302 Found')
 
        self.assertEqual(response.session['rhodecode_user'].get('username'),
 
        self.assertEqual(response.session['authuser'].get('username'),
 
                         'test_regular')
 
        response = response.follow()
 
        response.mustcontain('/%s' % HG_REPO)
 

	
 
    def test_login_ok_came_from(self):
 
        test_came_from = '/_admin/users'
 
        response = self.app.post(url(controller='login', action='index',
 
                                     came_from=test_came_from),
 
                                 {'username': 'test_admin',
 
                                  'password': 'test12'})
 
        self.assertEqual(response.status, '302 Found')
 
        response = response.follow()
 

	
 
        self.assertEqual(response.status, '200 OK')
 
        response.mustcontain('Users administration')
 

	
 
    @parameterized.expand([
 
          ('data:text/html,<script>window.alert("xss")</script>',),
 
          ('mailto:test@example.com',),
 
          ('file:///etc/passwd',),
 
          ('ftp://some.ftp.server',),
 
          ('http://other.domain',),
 
    ])
 
    def test_login_bad_came_froms(self, url_came_from):
 
        response = self.app.post(url(controller='login', action='index',
 
                                     came_from=url_came_from),
 
                                 {'username': 'test_admin',
 
                                  'password': 'test12'})
 
        self.assertEqual(response.status, '302 Found')
 
        self.assertEqual(response._environ['paste.testing_variables']
 
                         ['tmpl_context'].came_from, '/')
 
        response = response.follow()
 

	
 
        self.assertEqual(response.status, '200 OK')
 

	
 
    def test_login_short_password(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': 'test_admin',
 
                                  'password': 'as'})
 
        self.assertEqual(response.status, '200 OK')
 

	
 
        response.mustcontain('Enter 3 characters or more')
 

	
 
    def test_login_wrong_username_password(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': 'error',
 
                                  'password': 'test12'})
 

	
0 comments (0 inline, 0 general)