Changeset - bbe3f2ba52ca
[Not reviewed]
development.ini
Show inline comments
 
@@ -15,24 +15,26 @@ pdebug = false
 
################################################################################
 
#email_to = admin@localhost
 
#error_email_from = paste_error@localhost
 
#app_email_from = rhodecode-noreply@localhost
 
#error_message =
 

	
 
#smtp_server = mail.server.com
 
#smtp_username = 
 
#smtp_password = 
 
#smtp_port = 
 
#smtp_use_tls = false
 
#smtp_use_ssl = true
 
# Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
 
#smtp_auth = 
 

	
 
[server:main]
 
##nr of threads to spawn
 
threadpool_workers = 5
 

	
 
##max request before thread respawn
 
threadpool_max_requests = 6
 

	
 
##option to use threads of process
 
use_threadpool = true
 

	
 
use = egg:Paste#http
docs/api/api.rst
Show inline comments
 
@@ -49,63 +49,314 @@ API METHODS
 
    
 
pull
 
----
 

	
 
Pulls given repo from remote location. 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
 

	
 
INPUT::
 

	
 
    api_key:"<api_key>"
 
    method: "pull"
 
    args: {"repo":<repo_name>}
 
    args :    {
 
                "repo" : "<repo_name>"
 
              }
 

	
 
OUTPUT::
 

	
 
    result:"Pulled from <repo_name>"
 
    error:null
 

	
 
    
 
get_users
 
---------
 

	
 
Lists all existing users. This command can be executed only using api_key
 
belonging to user with admin rights.
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "get_users"
 
    args :    { }
 

	
 
OUTPUT::
 

	
 
    result: [
 
              {
 
                "id" :       "<id>",
 
                "username" : "<username>",
 
                "firstname": "<firstname>",
 
                "lastname" : "<lastname>",
 
                "email" :    "<email>",
 
                "active" :   "<bool>",
 
                "admin" :    "<bool>",
 
                "ldap" :     "<ldap_dn>"
 
              },
 
    	      …
 
            ]
 
    error:  null
 

	
 
create_user
 
-----------
 

	
 
Creates new user in RhodeCode. This command can be executed only using api_key 
 
belonging to user with admin rights
 
belonging to user with admin rights.
 

	
 
INPUT::
 

	
 
    api_key:"<api_key>"
 
    method: "create_user"
 
    args: {"username": "<username>", 
 
    args :    {
 
                "username" :  "<username>",
 
           "password": "<password>", 
 
           "active":   "<bool>", 
 
           "admin":    "<bool>", 
 
           "name":     "<firstname>", 
 
                "firstname" : "<firstname>",
 
           "lastname": "<lastname>", 
 
           "email":    "<useremail>"}
 
                "email" :     "<useremail>"
 
                "active" :    "<bool> = True",
 
                "admin" :     "<bool> = False",
 
                "ldap_dn" :   "<ldap_dn> = None"
 
              }
 

	
 
OUTPUT::
 

	
 
    result: {
 
              "msg" : "created new user <username>"
 
            }
 
    error:  null
 

	
 
get_users_groups
 
----------------
 

	
 
Lists all existing users groups. This command can be executed only using api_key
 
belonging to user with admin rights.
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "get_users_groups"
 
    args :    { }
 

	
 
OUTPUT::
 

	
 
    result:{"id": <newuserid>,
 
            "msg":"created new user <username>"}
 
    result : [
 
               {
 
                 "id" :       "<id>",
 
                 "name" :     "<name>",
 
                 "active":    "<bool>",
 
                 "members" :  [
 
	    	                    {
 
	    	                      "id" :       "<userid>",
 
	                              "username" : "<username>",
 
	                              "firstname": "<firstname>",
 
	                              "lastname" : "<lastname>",
 
	                              "email" :    "<email>",
 
	                              "active" :   "<bool>",
 
	                              "admin" :    "<bool>",
 
	                              "ldap" :     "<ldap_dn>"
 
	                            },
 
	    	                    …
 
	                          ]
 
	            }
 
              ]
 
    error:null
 
    
 
get_users_group
 
---------------
 

	
 
Gets an existing users group. This command can be executed only using api_key
 
belonging to user with admin rights.
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "get_users_group"
 
    args :    {
 
                "group_name" : "<name>"
 
              }
 

	
 
OUTPUT::
 

	
 
    result : None if group not exist
 
             {
 
               "id" :       "<id>",
 
               "name" :     "<name>",
 
               "active":    "<bool>",
 
               "members" :  [
 
	    	                  { "id" :       "<userid>",
 
	                            "username" : "<username>",
 
	                            "firstname": "<firstname>",
 
	                            "lastname" : "<lastname>",
 
	                            "email" :    "<email>",
 
	                            "active" :   "<bool>",
 
	                            "admin" :    "<bool>",
 
	                            "ldap" :     "<ldap_dn>"
 
	                          },
 
	    	                  …
 
	                        ]
 
             }
 
    error : null
 
    
 
create_users_group
 
------------------
 

	
 
creates new users group. This command can be executed only using api_key 
 
Creates new users group. This command can be executed only using api_key
 
belonging to user with admin rights
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "create_users_group"
 
    args:     {
 
                "name":  "<name>",
 
                "active":"<bool> = True"
 
              }
 

	
 
OUTPUT::
 

	
 
    result: {
 
              "id":  "<newusersgroupid>",
 
              "msg": "created new users group <name>"
 
            }
 
    error:  null
 

	
 
add_user_to_users_groups
 
------------------------
 

	
 
Adds a user to a users group. This command can be executed only using api_key
 
belonging to user with admin rights
 

	
 
INPUT::
 

	
 
    api_key:"<api_key>"
 
    method: "create_user"
 
    args: {"name":  "<groupname>", 
 
           "active":"<bool>"}
 
    method :  "add_user_users_group"
 
    args:     {
 
                "group_name" :  "<groupname>",
 
                "user_name" :   "<username>"
 
              }
 

	
 
OUTPUT::
 

	
 
    result: {
 
              "id":  "<newusersgroupmemberid>",
 
              "msg": "created new users group member"
 
            }
 
    error:  null
 

	
 
get_repos
 
---------
 

	
 
Lists all existing repositories. This command can be executed only using api_key
 
belonging to user with admin rights
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "get_repos"
 
    args:     { }
 

	
 
OUTPUT::
 

	
 
    result: [
 
              {
 
                "id" :          "<id>",
 
                "name" :        "<name>"
 
                "type" :        "<type>",
 
                "description" : "<description>"
 
              },
 
              …
 
            ]
 
    error:  null
 

	
 
get_repo
 
--------
 

	
 
Gets an existing repository. This command can be executed only using api_key
 
belonging to user with admin rights
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "get_repo"
 
    args:     {
 
                "name" : "<name>"
 
              }
 

	
 
OUTPUT::
 

	
 
    result:{"id": <newusersgroupid>,
 
            "msg":"created new users group <groupname>"}
 
    result: None if repository not exist
 
            {
 
                "id" :          "<id>",
 
                "name" :        "<name>"
 
                "type" :        "<type>",
 
                "description" : "<description>",
 
                "members" :     [
 
                                  { "id" :         "<userid>",
 
	                                "username" :   "<username>",
 
	                                "firstname":   "<firstname>",
 
	                                "lastname" :   "<lastname>",
 
	                                "email" :      "<email>",
 
	                                "active" :     "<bool>",
 
	                                "admin" :      "<bool>",
 
	                                "ldap" :       "<ldap_dn>",
 
	                                "permission" : "repository_(read|write|admin)"
 
	                              },
 
                                  …
 
                                  {
 
                                    "id" :       "<usersgroupid>",
 
                                    "name" :     "<usersgroupname>",
 
                                    "active":    "<bool>",
 
                                    "permission" : "repository_(read|write|admin)"
 
                                  },
 
                                  …
 
                                ]
 
            }
 
    error:null    
 

	
 
create_repo
 
-----------
 

	
 
Creates a repository. This command can be executed only using api_key
 
belonging to user with admin rights.
 
If repository name contains "/", all needed repository groups will be created.
 
For example "foo/bar/baz" will create groups "foo", "bar" (with "foo" as parent),
 
and create "baz" repository with "bar" as group.
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "create_repo"
 
    args:     {
 
                "name" :        "<name>",
 
                "owner_name" :  "<ownername>",
 
                "description" : "<description> = ''",
 
                "repo_type" :   "<type> = 'hg'",
 
                "private" :     "<bool> = False"
 
              }
 

	
 
OUTPUT::
 

	
 
    result: None
 
    error:  null
 

	
 
add_user_to_repo
 
----------------
 

	
 
Add a user to a repository. This command can be executed only using api_key
 
belonging to user with admin rights.
 
If "perm" is None, user will be removed from the repository.
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "add_user_to_repo"
 
    args:     {
 
                "repo_name" :  "<reponame>",
 
                "user_name" :  "<username>",
 
                "perm" :       "(None|repository_(read|write|admin))",
 
              }
 

	
 
OUTPUT::
 

	
 
    result: None
 
    error:  null
production.ini
Show inline comments
 
@@ -15,24 +15,26 @@ pdebug = false
 
################################################################################
 
#email_to = admin@localhost
 
#error_email_from = paste_error@localhost
 
#app_email_from = rhodecode-noreply@localhost
 
#error_message =
 

	
 
#smtp_server = mail.server.com
 
#smtp_username = 
 
#smtp_password = 
 
#smtp_port = 
 
#smtp_use_tls = false
 
#smtp_use_ssl = true
 
# Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
 
#smtp_auth = 
 

	
 
[server:main]
 
##nr of threads to spawn
 
threadpool_workers = 5
 

	
 
##max request before thread respawn
 
threadpool_max_requests = 10
 

	
 
##option to use threads of process
 
use_threadpool = true
 

	
 
use = egg:Paste#http
rhodecode/config/deployment.ini_tmpl
Show inline comments
 
@@ -15,24 +15,26 @@ pdebug = false
 
################################################################################
 
#email_to = admin@localhost
 
#error_email_from = paste_error@localhost
 
#app_email_from = rhodecode-noreply@localhost
 
#error_message =
 

	
 
#smtp_server = mail.server.com
 
#smtp_username = 
 
#smtp_password = 
 
#smtp_port = 
 
#smtp_use_tls = false
 
#smtp_use_ssl = true
 
# Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
 
#smtp_auth = 
 

	
 
[server:main]
 
##nr of threads to spawn
 
threadpool_workers = 5
 

	
 
##max request before thread respawn
 
threadpool_max_requests = 10
 

	
 
##option to use threads of process
 
use_threadpool = true
 

	
 
use = egg:Paste#http
 
@@ -138,25 +140,25 @@ set debug = false
 
##################################
 
logview.sqlalchemy = #faa
 
logview.pylons.templating = #bfb
 
logview.pylons.util = #eee
 

	
 
#########################################################
 
### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG    ###
 
#########################################################
 

	
 
# SQLITE [default]
 
sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
 
 
 
# POSTGRES
 
# POSTGRESQL
 
# sqlalchemy.db1.url = postgresql://user:pass@localhost/rhodecode
 

	
 
# MySQL
 
# sqlalchemy.db1.url = mysql://user:pass@localhost/rhodecode
 

	
 

	
 
sqlalchemy.db1.echo = false
 
sqlalchemy.db1.pool_recycle = 3600
 
sqlalchemy.convert_unicode = true
 

	
 
################################
 
### LOGGING CONFIGURATION   ####
rhodecode/controllers/admin/repos.py
Show inline comments
 
@@ -17,25 +17,24 @@
 
#
 
# 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/>.
 

	
 
import logging
 
import traceback
 
import formencode
 
from operator import itemgetter
 
from formencode import htmlfill
 

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

	
 
from rhodecode.lib import helpers as h
 
from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
 
    HasPermissionAnyDecorator
 
from rhodecode.lib.base import BaseController, render
 
from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
 
@@ -83,66 +82,43 @@ class ReposController(BaseController):
 
        repo = db_repo.scm_instance
 

	
 
        if c.repo_info is None:
 
            h.flash(_('%s repository is not mapped to db perhaps'
 
                      ' it was created or renamed from the filesystem'
 
                      ' please run the application again'
 
                      ' in order to rescan repositories') % repo_name,
 
                      category='error')
 

	
 
            return redirect(url('repos'))
 

	
 
        c.default_user_id = User.get_by_username('default').user_id
 
        c.in_public_journal = self.sa.query(UserFollowing)\
 
        c.in_public_journal = UserFollowing.query()\
 
            .filter(UserFollowing.user_id == c.default_user_id)\
 
            .filter(UserFollowing.follows_repository == c.repo_info).scalar()
 

	
 
        if c.repo_info.stats:
 
            last_rev = c.repo_info.stats.stat_on_revision
 
        else:
 
            last_rev = 0
 
        c.stats_revision = last_rev
 

	
 
        c.repo_last_rev = repo.count() - 1 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)
 

	
 
        defaults = c.repo_info.get_dict()
 
        group, repo_name = c.repo_info.groups_and_repo
 
        defaults['repo_name'] = repo_name
 
        defaults['repo_group'] = getattr(group[-1] if group else None,
 
                                         'group_id', None)
 

	
 
        #fill owner
 
        if c.repo_info.user:
 
            defaults.update({'user': c.repo_info.user.username})
 
        else:
 
            replacement_user = self.sa.query(User)\
 
            .filter(User.admin == True).first().username
 
            defaults.update({'user': replacement_user})
 

	
 
        #fill repository users
 
        for p in c.repo_info.repo_to_perm:
 
            defaults.update({'u_perm_%s' % p.user.username:
 
                             p.permission.permission_name})
 

	
 
        #fill repository groups
 
        for p in c.repo_info.users_group_to_perm:
 
            defaults.update({'g_perm_%s' % p.users_group.users_group_name:
 
                             p.permission.permission_name})
 

	
 
        defaults = RepoModel()._get_defaults(repo_name)
 
        return defaults
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def index(self, format='html'):
 
        """GET /repos: All items in the collection"""
 
        # url('repos')
 

	
 
        c.repos_list = ScmModel().get_repos(Repository.query()
 
                                            .order_by(Repository.repo_name)
 
                                            .all(), sort_key='name_sort')
 
        return render('admin/repos/repos.html')
 

	
rhodecode/controllers/api/api.py
Show inline comments
 
import traceback
 
import logging
 

	
 
from rhodecode.controllers.api import JSONRPCController, JSONRPCError
 
from rhodecode.lib.auth import HasPermissionAllDecorator
 
from rhodecode.lib.auth import HasPermissionAllDecorator, \
 
    HasPermissionAnyDecorator
 
from rhodecode.model.scm import ScmModel
 

	
 
from rhodecode.model.db import User, UsersGroup, Repository
 
from rhodecode.model.db import User, UsersGroup, Group, Repository
 
from rhodecode.model.repo import RepoModel
 
from rhodecode.model.user import UserModel
 
from rhodecode.model.repo_permission import RepositoryPermissionModel
 
from rhodecode.model.users_group import UsersGroupModel
 
from rhodecode.model import users_group
 
from rhodecode.model.repos_group import ReposGroupModel
 
from sqlalchemy.orm.exc import NoResultFound
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class ApiController(JSONRPCController):
 
    """
 
    API Controller
 
    
 
    
 
    Each method needs to have USER as argument this is then based on given
 
    API_KEY propagated as instance of user object
 
    
 
@@ -36,63 +44,332 @@ class ApiController(JSONRPCController):
 
        :param repo:
 
        """
 

	
 
        if Repository.is_valid(repo) is False:
 
            raise JSONRPCError('Unknown repo "%s"' % repo)
 
        
 
        try:
 
            ScmModel().pull_changes(repo, self.rhodecode_user.username)
 
            return 'Pulled from %s' % repo
 
        except Exception:
 
            raise JSONRPCError('Unable to pull changes from "%s"' % repo)
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def get_user(self, apiuser, username):
 
        """"
 
        Get a user by username
 

	
 
        :param apiuser
 
        :param username
 
        """
 

	
 
        user = User.get_by_username(username)
 
        if not user:
 
            return None
 

	
 
        return dict(id=user.user_id,
 
                        username=user.username,
 
                        firstname=user.name,
 
                        lastname=user.lastname,
 
                        email=user.email,
 
                        active=user.active,
 
                        admin=user.admin,
 
                        ldap=user.ldap_dn)
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def create_user(self, apiuser, username, password, active, admin, name, 
 
                    lastname, email):
 
    def get_users(self, apiuser):
 
        """"
 
        Get all users
 

	
 
        :param apiuser
 
        """
 
        Creates new user
 

	
 
        result = []
 
        for user in User.getAll():
 
            result.append(dict(id=user.user_id,
 
                                username=user.username,
 
                                firstname=user.name,
 
                                lastname=user.lastname,
 
                                email=user.email,
 
                                active=user.active,
 
                                admin=user.admin,
 
                                ldap=user.ldap_dn))
 
        return result
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def create_user(self, apiuser, username, password, firstname,
 
                    lastname, email, active=True, admin=False, ldap_dn=None):
 
        """
 
        Create new user
 
        
 
        :param apiuser:
 
        :param username:
 
        :param password:
 
        :param active:
 
        :param admin:
 
        :param name:
 
        :param lastname:
 
        :param email:
 
        :param active:
 
        :param admin:
 
        :param ldap_dn:
 
        """
 
        
 
        if self.get_user(apiuser, username):
 
            raise JSONRPCError("user %s already exist" % username)
 

	
 
        try:
 
        form_data = dict(username=username,
 
                         password=password,
 
                         active=active,
 
                         admin=admin,
 
                         name=name,
 
                             name=firstname,
 
                         lastname=lastname,
 
                         email=email)
 
        try:
 
            u = User.create(form_data)
 
            return {'id':u.user_id,
 
                    'msg':'created new user %s' % name}
 
                             email=email,
 
                             ldap_dn=ldap_dn)
 
            UserModel().create_ldap(username, password, ldap_dn, form_data)
 
            return dict(msg='created new user %s' % username)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to create user %s' % name)
 

	
 
            raise JSONRPCError('failed to create user %s' % username)
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def create_users_group(self, apiuser, name, active):
 
    def get_users_group(self, apiuser, group_name):
 
        """"
 
        Get users group by name
 

	
 
        :param apiuser
 
        :param group_name
 
        """
 

	
 
        users_group = UsersGroup.get_by_group_name(group_name)
 
        if not users_group:
 
            return None
 

	
 
        members = []
 
        for user in users_group.members:
 
            user = user.user
 
            members.append(dict(id=user.user_id,
 
                            username=user.username,
 
                            firstname=user.name,
 
                            lastname=user.lastname,
 
                            email=user.email,
 
                            active=user.active,
 
                            admin=user.admin,
 
                            ldap=user.ldap_dn))
 

	
 
        return dict(id=users_group.users_group_id,
 
                    name=users_group.users_group_name,
 
                    active=users_group.users_group_active,
 
                    members=members)
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def get_users_groups(self, apiuser):
 
        """"
 
        Get all users groups
 

	
 
        :param apiuser
 
        """
 

	
 
        result = []
 
        for users_group in UsersGroup.getAll():
 
            members = []
 
            for user in users_group.members:
 
                user = user.user
 
                members.append(dict(id=user.user_id,
 
                                username=user.username,
 
                                firstname=user.name,
 
                                lastname=user.lastname,
 
                                email=user.email,
 
                                active=user.active,
 
                                admin=user.admin,
 
                                ldap=user.ldap_dn))
 

	
 
            result.append(dict(id=users_group.users_group_id,
 
                                name=users_group.users_group_name,
 
                                active=users_group.users_group_active,
 
                                members=members))
 
        return result
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def create_users_group(self, apiuser, name, active=True):
 
        """
 
        Creates an new usergroup
 
        
 
        :param name:
 
        :param active:
 
        """
 
        form_data = {'users_group_name':name,
 
                     'users_group_active':active}
 

	
 
        if self.get_users_group(apiuser, name):
 
            raise JSONRPCError("users group %s already exist" % name)
 

	
 
        try:
 
            form_data = dict(users_group_name=name,
 
                             users_group_active=active)
 
            ug = UsersGroup.create(form_data)
 
            return {'id':ug.users_group_id,
 
                    'msg':'created new users group %s' % name}
 
            return dict(id=ug.users_group_id,
 
                        msg='created new users group %s' % name)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to create group %s' % name)
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def add_user_to_users_group(self, apiuser, group_name, user_name):
 
        """"
 
        Add a user to a group
 

	
 
        :param apiuser
 
        :param group_name
 
        :param user_name
 
        """
 

	
 
        try:
 
            users_group = UsersGroup.get_by_group_name(group_name)
 
            if not users_group:
 
                raise JSONRPCError('unknown users group %s' % group_name)
 

	
 
            try:
 
                user = User.get_by_username(user_name)
 
            except NoResultFound:
 
                raise JSONRPCError('unknown user %s' % user_name)
 

	
 
            ugm = UsersGroupModel().add_user_to_group(users_group, user)
 

	
 
            return dict(id=ugm.users_group_member_id,
 
                        msg='created new users group member')
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to create users group member')
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def get_repo(self, apiuser, repo_name):
 
        """"
 
        Get repository by name
 

	
 
        :param apiuser
 
        :param repo_name
 
        """
 

	
 
        try:
 
            repo = Repository.get_by_repo_name(repo_name)
 
        except NoResultFound:
 
            return None
 

	
 
        members = []
 
        for user in repo.repo_to_perm:
 
            perm = user.permission.permission_name
 
            user = user.user
 
            members.append(dict(type_="user",
 
                                    id=user.user_id,
 
                                    username=user.username,
 
                                    firstname=user.name,
 
                                    lastname=user.lastname,
 
                                    email=user.email,
 
                                    active=user.active,
 
                                    admin=user.admin,
 
                                    ldap=user.ldap_dn,
 
                                    permission=perm))
 
        for users_group in repo.users_group_to_perm:
 
            perm = users_group.permission.permission_name
 
            users_group = users_group.users_group
 
            members.append(dict(type_="users_group",
 
                                    id=users_group.users_group_id,
 
                                    name=users_group.users_group_name,
 
                                    active=users_group.users_group_active,
 
                                    permission=perm))
 

	
 
        return dict(id=repo.repo_id,
 
                    name=repo.repo_name,
 
                    type=repo.repo_type,
 
                    description=repo.description,
 
                    members=members)
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def get_repos(self, apiuser):
 
        """"
 
        Get all repositories
 

	
 
        :param apiuser
 
        """
 

	
 
        result = []
 
        for repository in Repository.getAll():
 
            result.append(dict(id=repository.repo_id,
 
                                name=repository.repo_name,
 
                                type=repository.repo_type,
 
                                description=repository.description))
 
        return result
 

	
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
 
    def create_repo(self, apiuser, name, owner_name, description='', 
 
                    repo_type='hg', private=False):
 
        """
 
        Create a repository
 

	
 
        :param apiuser
 
        :param name
 
        :param description
 
        :param type
 
        :param private
 
        :param owner_name
 
        """
 

	
 
        try:
 
            try:
 
                owner = User.get_by_username(owner_name)
 
            except NoResultFound:
 
                raise JSONRPCError('unknown user %s' % owner)
 

	
 
            if self.get_repo(apiuser, name):
 
                raise JSONRPCError("repo %s already exist" % name)
 

	
 
            groups = name.split('/')
 
            real_name = groups[-1]
 
            groups = groups[:-1]
 
            parent_id = None
 
            for g in groups:
 
                group = Group.get_by_group_name(g)
 
                if not group:
 
                    group = ReposGroupModel().create(dict(group_name=g,
 
                                                  group_description='',
 
                                                  group_parent_id=parent_id))
 
                parent_id = group.group_id
 

	
 
            RepoModel().create(dict(repo_name=real_name,
 
                                     repo_name_full=name,
 
                                     description=description,
 
                                     private=private,
 
                                     repo_type=repo_type,
 
                                     repo_group=parent_id,
 
                                     clone_uri=None), owner)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to create repository %s' % name)
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def add_user_to_repo(self, apiuser, repo_name, user_name, perm):
 
        """
 
        Add permission for a user to a repository
 

	
 
        :param apiuser
 
        :param repo_name
 
        :param user_name
 
        :param perm
 
        """
 

	
 
        try:
 
            try:
 
                repo = Repository.get_by_repo_name(repo_name)
 
            except NoResultFound:
 
                raise JSONRPCError('unknown repository %s' % repo)
 

	
 
            try:
 
                user = User.get_by_username(user_name)
 
            except NoResultFound:
 
                raise JSONRPCError('unknown user %s' % user)
 

	
 
            RepositoryPermissionModel()\
 
                .update_or_delete_user_permission(repo, user, perm)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to edit permission %(repo)s for %(user)s'
 
                            % dict(user=user_name, repo=repo_name))
 

	
 
        
 
\ No newline at end of file
rhodecode/controllers/settings.py
Show inline comments
 
@@ -33,91 +33,85 @@ from pylons import tmpl_context as c, re
 
from pylons.controllers.util import redirect
 
from pylons.i18n.translation import _
 

	
 
import rhodecode.lib.helpers as h
 

	
 
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAllDecorator, \
 
    HasRepoPermissionAnyDecorator, NotAnonymous
 
from rhodecode.lib.base import BaseRepoController, render
 
from rhodecode.lib.utils import invalidate_cache, action_logger
 

	
 
from rhodecode.model.forms import RepoSettingsForm, RepoForkForm
 
from rhodecode.model.repo import RepoModel
 
from rhodecode.model.db import User
 
from rhodecode.model.db import Group
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class SettingsController(BaseRepoController):
 

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

	
 
    def __load_defaults(self):
 
        c.repo_groups = Group.groups_choices()
 
        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.users_groups_array = repo_model.get_users_groups_js()
 
        
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def index(self, repo_name):
 
        repo_model = RepoModel()
 
        c.repo_info = repo = repo_model.get_by_repo_name(repo_name)
 
        if not repo:
 
            h.flash(_('%s repository is not mapped to db perhaps'
 
                      ' it was created or renamed from the file system'
 
                      ' please run the application again'
 
                      ' in order to rescan repositories') % repo_name,
 
                      category='error')
 

	
 
            return redirect(url('home'))
 

	
 
        c.users_array = repo_model.get_users_js()
 
        c.users_groups_array = repo_model.get_users_groups_js()
 

	
 
        defaults = c.repo_info.get_dict()
 
        self.__load_defaults()
 

	
 
        #fill owner
 
        if c.repo_info.user:
 
            defaults.update({'user': c.repo_info.user.username})
 
        else:
 
            replacement_user = self.sa.query(User)\
 
            .filter(User.admin == True).first().username
 
            defaults.update({'user': replacement_user})
 

	
 
        #fill repository users
 
        for p in c.repo_info.repo_to_perm:
 
            defaults.update({'u_perm_%s' % p.user.username:
 
                             p.permission.permission_name})
 

	
 
        #fill repository groups
 
        for p in c.repo_info.users_group_to_perm:
 
            defaults.update({'g_perm_%s' % p.users_group.users_group_name:
 
                             p.permission.permission_name})
 
        defaults = RepoModel()._get_defaults(repo_name)
 

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

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def update(self, repo_name):
 
        repo_model = RepoModel()
 
        changed_name = repo_name
 
        
 
        self.__load_defaults()
 
        
 
        _form = RepoSettingsForm(edit=True,
 
                                 old_data={'repo_name': repo_name})()
 
                                 old_data={'repo_name': repo_name},
 
                                 repo_groups=c.repo_groups_choices)()
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            
 
            repo_model.update(repo_name, form_result)
 
            invalidate_cache('get_repo_cached_%s' % repo_name)
 
            h.flash(_('Repository %s updated successfully' % repo_name),
 
                    category='success')
 
            changed_name = form_result['repo_name']
 
            changed_name = form_result['repo_name_full']
 
            action_logger(self.rhodecode_user, 'user_updated_repo',
 
                              changed_name, '', self.sa)
 
        except formencode.Invalid, errors:
 
            c.repo_info = repo_model.get_by_repo_name(repo_name)
 
            c.users_array = repo_model.get_users_js()
 
            errors.value.update({'user': c.repo_info.user.username})
 
            return htmlfill.render(
 
                render('settings/repo_settings.html'),
 
                defaults=errors.value,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8")
rhodecode/lib/__init__.py
Show inline comments
 
@@ -385,24 +385,23 @@ def get_changeset_safe(repo, rev):
 

	
 
def get_current_revision(quiet=False):
 
    """
 
    Returns tuple of (number, id) from repository containing this package
 
    or None if repository could not be found.
 
    
 
    :param quiet: prints error for fetching revision if True
 
    """
 

	
 
    try:
 
        from vcs import get_repo
 
        from vcs.utils.helpers import get_scm
 
        from vcs.exceptions import RepositoryError, VCSError
 
        repopath = os.path.join(os.path.dirname(__file__), '..', '..')
 
        scm = get_scm(repopath)[0]
 
        repo = get_repo(path=repopath, alias=scm)
 
        tip = repo.get_changeset()
 
        return (tip.revision, tip.short_id)
 
    except (ImportError, RepositoryError, VCSError), err:
 
    except Exception, err:
 
        if not quiet:
 
            print ("Cannot retrieve rhodecode's revision. Original error "
 
                   "was: %s" % err)
 
        return None
 

	
rhodecode/lib/auth_ldap.py
Show inline comments
 
@@ -45,59 +45,63 @@ class AuthLdap(object):
 
                 ldap_filter='(&(objectClass=user)(!(objectClass=computer)))',
 
                 search_scope='SUBTREE',
 
                 attr_login='uid'):
 
        self.ldap_version = ldap_version
 
        ldap_server_type = 'ldap'
 

	
 
        self.TLS_KIND = tls_kind
 

	
 
        if self.TLS_KIND == 'LDAPS':
 
            port = port or 689
 
            ldap_server_type = ldap_server_type + 's'
 

	
 
        self.TLS_REQCERT = ldap.__dict__['OPT_X_TLS_' + tls_reqcert]
 
        OPT_X_TLS_DEMAND = 2
 
        self.TLS_REQCERT = getattr(ldap, 'OPT_X_TLS_%s' % tls_reqcert, 
 
                                   OPT_X_TLS_DEMAND)
 
        self.LDAP_SERVER_ADDRESS = server
 
        self.LDAP_SERVER_PORT = port
 

	
 
        #USE FOR READ ONLY BIND TO LDAP SERVER
 
        self.LDAP_BIND_DN = bind_dn
 
        self.LDAP_BIND_PASS = bind_pass
 

	
 
        self.LDAP_SERVER = "%s://%s:%s" % (ldap_server_type,
 
                                               self.LDAP_SERVER_ADDRESS,
 
                                               self.LDAP_SERVER_PORT)
 

	
 
        self.BASE_DN = base_dn
 
        self.LDAP_FILTER = ldap_filter
 
        self.SEARCH_SCOPE = ldap.__dict__['SCOPE_' + search_scope]
 
        self.SEARCH_SCOPE = getattr(ldap, 'SCOPE_%s' % search_scope)
 
        self.attr_login = attr_login
 

	
 
    def authenticate_ldap(self, username, password):
 
        """Authenticate a user via LDAP and return his/her LDAP properties.
 

	
 
        Raises AuthenticationError if the credentials are rejected, or
 
        EnvironmentError if the LDAP server can't be reached.
 

	
 
        :param username: username
 
        :param password: password
 
        """
 

	
 
        from rhodecode.lib.helpers import chop_at
 

	
 
        uid = chop_at(username, "@%s" % self.LDAP_SERVER_ADDRESS)
 

	
 
        if "," in username:
 
            raise LdapUsernameError("invalid character in username: ,")
 
        try:
 
            ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, '/etc/openldap/cacerts')
 
            if hasattr(ldap,'OPT_X_TLS_CACERTDIR'):
 
                ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, 
 
                                '/etc/openldap/cacerts')
 
            ldap.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF)
 
            ldap.set_option(ldap.OPT_RESTART, ldap.OPT_ON)
 
            ldap.set_option(ldap.OPT_TIMEOUT, 20)
 
            ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, 10)
 
            ldap.set_option(ldap.OPT_TIMELIMIT, 15)
 
            if self.TLS_KIND != 'PLAIN':
 
                ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, self.TLS_REQCERT)
 
            server = ldap.initialize(self.LDAP_SERVER)
 
            if self.ldap_version == 2:
 
                server.protocol = ldap.VERSION2
 
            else:
 
                server.protocol = ldap.VERSION3
rhodecode/lib/celerylib/tasks.py
Show inline comments
 
@@ -347,27 +347,28 @@ def send_email(recipients, subject, body
 

	
 
    if not recipients:
 
        recipients = [email_config.get('email_to')]
 

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

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

	
 

	
 
@task(ignore_result=True)
 
def create_repo_fork(form_data, cur_user):
 
    from rhodecode.model.repo import RepoModel
rhodecode/lib/middleware/simplegit.py
Show inline comments
 
@@ -158,24 +158,26 @@ class SimpleGit(object):
 
                    else:
 
                        return result.wsgi_application(environ, start_response)
 

	
 
                #==============================================================
 
                # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME FROM
 
                # BASIC AUTH
 
                #==============================================================
 

	
 
                if action in ['pull', 'push']:
 
                    username = REMOTE_USER(environ)
 
                    try:
 
                        user = self.__get_user(username)
 
                        if user is None:
 
                            return HTTPForbidden()(environ, start_response)                        
 
                        username = user.username
 
                    except:
 
                        log.error(traceback.format_exc())
 
                        return HTTPInternalServerError()(environ,
 
                                                         start_response)
 

	
 
                    #check permissions for this repository
 
                    perm = self.__check_permission(action, user,
 
                                                   repo_name)
 
                    if perm is not True:
 
                        return HTTPForbidden()(environ, start_response)
 

	
rhodecode/lib/smtp_mailer.py
Show inline comments
 
@@ -30,63 +30,66 @@ from socket import sslerror
 
from email.mime.multipart import MIMEMultipart
 
from email.mime.image import MIMEImage
 
from email.mime.audio import MIMEAudio
 
from email.mime.base import MIMEBase
 
from email.mime.text import MIMEText
 
from email.utils import formatdate
 
from email import encoders
 

	
 

	
 
class SmtpMailer(object):
 
    """SMTP mailer class
 

	
 
    mailer = SmtpMailer(mail_from, user, passwd, mail_server,
 
    mailer = SmtpMailer(mail_from, user, passwd, mail_server, smtp_auth
 
                        mail_port, ssl, tls)
 
    mailer.send(recipients, subject, body, attachment_files)
 

	
 
    :param recipients might be a list of string or single string
 
    :param attachment_files is a dict of {filename:location}
 
        it tries to guess the mimetype and attach the file
 

	
 
    """
 

	
 
    def __init__(self, mail_from, user, passwd, mail_server,
 
    def __init__(self, mail_from, user, passwd, mail_server, smtp_auth=None,
 
                    mail_port=None, ssl=False, tls=False, debug=False):
 

	
 
        self.mail_from = mail_from
 
        self.mail_server = mail_server
 
        self.mail_port = mail_port
 
        self.user = user
 
        self.passwd = passwd
 
        self.ssl = ssl
 
        self.tls = tls
 
        self.debug = debug
 
        self.auth = smtp_auth
 

	
 
    def send(self, recipients=[], subject='', body='', attachment_files=None):
 

	
 
        if isinstance(recipients, basestring):
 
            recipients = [recipients]
 
        if self.ssl:
 
            smtp_serv = smtplib.SMTP_SSL(self.mail_server, self.mail_port)
 
        else:
 
            smtp_serv = smtplib.SMTP(self.mail_server, self.mail_port)
 

	
 
        if self.tls:
 
            smtp_serv.ehlo()
 
            smtp_serv.starttls()
 

	
 
        if self.debug:
 
            smtp_serv.set_debuglevel(1)
 

	
 
        smtp_serv.ehlo()
 
        if self.auth:
 
            smtp_serv.esmtp_features["auth"] = self.auth
 

	
 
        #if server requires authorization you must provide login and password
 
        #but only if we have them
 
        if self.user and self.passwd:
 
            smtp_serv.login(self.user, self.passwd)
 

	
 
        date_ = formatdate(localtime=True)
 
        msg = MIMEMultipart()
 
        msg.set_type('multipart/alternative')
 
        msg.preamble = 'You will not see this in a MIME-aware mail reader.\n'
 

	
 
        text_msg = MIMEText(body)
 
@@ -150,12 +153,13 @@ class SmtpMailer(object):
 
    def get_content(self, msg_file):
 
        """Get content based on type, if content is a string do open first
 
        else just read because it's a probably open file object
 

	
 
        :param msg_file:
 
        """
 
        if isinstance(msg_file, str):
 
            return open(msg_file, "rb").read()
 
        else:
 
            #just for safe seek to 0
 
            msg_file.seek(0)
 
            return msg_file.read()
 

	
rhodecode/model/db.py
Show inline comments
 
@@ -21,29 +21,26 @@
 
# 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/>.
 

	
 
import os
 
import logging
 
import datetime
 
import traceback
 
from datetime import date
 

	
 
from sqlalchemy import *
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.ext.hybrid import hybrid_property
 
from sqlalchemy.orm import relationship, backref, joinedload, class_mapper, \
 
    validates
 
from sqlalchemy.orm.interfaces import MapperExtension
 
from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
 
from beaker.cache import cache_region, region_invalidate
 

	
 
from vcs import get_backend
 
from vcs.utils.helpers import get_scm
 
from vcs.exceptions import VCSError
 
from vcs.utils.lazy import LazyProperty
 

	
 
from rhodecode.lib import str2bool, safe_str, get_changeset_safe, \
 
    generate_api_key, safe_unicode
 
from rhodecode.lib.exceptions import UsersGroupsAssignedException
 
from rhodecode.lib.compat import json
 

	
 
@@ -120,29 +117,33 @@ class BaseModel(object):
 

	
 
        for k in self._get_keys():
 
            if k in populate_dict:
 
                setattr(self, k, populate_dict[k])
 

	
 
    @classmethod
 
    def query(cls):
 
        return Session.query(cls)
 

	
 
    @classmethod
 
    def get(cls, id_):
 
        if id_:
 
            return Session.query(cls).get(id_)
 
            return cls.query().get(id_)
 

	
 
    @classmethod
 
    def getAll(cls):
 
        return cls.query().all()
 

	
 
    @classmethod
 
    def delete(cls, id_):
 
        obj = Session.query(cls).get(id_)
 
        obj = cls.query().get(id_)
 
        Session.delete(obj)
 
        Session.commit()
 

	
 

	
 
class RhodeCodeSettings(Base, BaseModel):
 
    __tablename__ = 'rhodecode_settings'
 
    __table_args__ = (UniqueConstraint('app_settings_name'), {'extend_existing':True})
 
    app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    app_settings_name = Column("app_settings_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    _app_settings_value = Column("app_settings_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    def __init__(self, k='', v=''):
 
@@ -169,47 +170,47 @@ class RhodeCodeSettings(Base, BaseModel)
 
        
 
        :param val:
 
        """
 
        self._app_settings_value = safe_unicode(val)
 

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

	
 

	
 
    @classmethod
 
    def get_by_name(cls, ldap_key):
 
        return Session.query(cls)\
 
        return cls.query()\
 
            .filter(cls.app_settings_name == ldap_key).scalar()
 

	
 
    @classmethod
 
    def get_app_settings(cls, cache=False):
 

	
 
        ret = Session.query(cls)
 
        ret = cls.query()
 

	
 
        if cache:
 
            ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
 

	
 
        if not ret:
 
            raise Exception('Could not get application settings !')
 
        settings = {}
 
        for each in ret:
 
            settings['rhodecode_' + each.app_settings_name] = \
 
                each.app_settings_value
 

	
 
        return settings
 

	
 
    @classmethod
 
    def get_ldap_settings(cls, cache=False):
 
        ret = Session.query(cls)\
 
        ret = cls.query()\
 
                .filter(cls.app_settings_name.startswith('ldap_')).all()
 
        fd = {}
 
        for row in ret:
 
            fd.update({row.app_settings_name:row.app_settings_value})
 

	
 
        return fd
 

	
 

	
 
class RhodeCodeUi(Base, BaseModel):
 
    __tablename__ = 'rhodecode_ui'
 
    __table_args__ = (UniqueConstraint('ui_key'), {'extend_existing':True})
 

	
 
@@ -218,25 +219,25 @@ class RhodeCodeUi(Base, BaseModel):
 
    HOOK_PUSH = 'pretxnchangegroup.push_logger'
 
    HOOK_PULL = 'preoutgoing.pull_logger'
 

	
 
    ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_value = Column("ui_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
 

	
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return Session.query(cls).filter(cls.ui_key == key)
 
        return cls.query().filter(cls.ui_key == key)
 

	
 

	
 
    @classmethod
 
    def get_builtin_hooks(cls):
 
        q = cls.query()
 
        q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE,
 
                                    cls.HOOK_REPO_SIZE,
 
                                    cls.HOOK_PUSH, cls.HOOK_PULL]))
 
        return q.all()
 

	
 
    @classmethod
 
    def get_custom_hooks(cls):
 
@@ -302,25 +303,25 @@ class User(Base, BaseModel):
 
        except:
 
            return self.__class__.__name__
 

	
 
    @classmethod
 
    def get_by_username(cls, username, case_insensitive=False):
 
        if case_insensitive:
 
            return Session.query(cls).filter(cls.username.ilike(username)).scalar()
 
        else:
 
            return Session.query(cls).filter(cls.username == username).scalar()
 

	
 
    @classmethod
 
    def get_by_api_key(cls, api_key):
 
        return Session.query(cls).filter(cls.api_key == api_key).one()
 
        return cls.query().filter(cls.api_key == api_key).one()
 

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

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

	
 
    @classmethod
 
    def create(cls, form_data):
 
        from rhodecode.lib.auth import get_crypt_password
 
@@ -367,38 +368,38 @@ class UsersGroup(Base, BaseModel):
 
    users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
 

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

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

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

	
 

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

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

	
 
@@ -413,28 +414,28 @@ class UsersGroup(Base, BaseModel):
 
    @classmethod
 
    def update(cls, users_group_id, form_data):
 

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

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

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

	
 
    @classmethod
 
    def delete(cls, users_group_id):
 
@@ -448,40 +449,48 @@ class UsersGroup(Base, BaseModel):
 
            if assigned_groups:
 
                raise UsersGroupsAssignedException('Group assigned to %s' %
 
                                                   assigned_groups)
 

	
 
            users_group = cls.get(users_group_id, cache=False)
 
            Session.delete(users_group)
 
            Session.commit()
 
        except:
 
            log.error(traceback.format_exc())
 
            Session.rollback()
 
            raise
 

	
 

	
 
class UsersGroupMember(Base, BaseModel):
 
    __tablename__ = 'users_groups_members'
 
    __table_args__ = {'extend_existing':True}
 

	
 
    users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User', lazy='joined')
 
    users_group = relationship('UsersGroup')
 

	
 
    def __init__(self, gr_id='', u_id=''):
 
        self.users_group_id = gr_id
 
        self.user_id = u_id
 

	
 
    @staticmethod
 
    def add_user_to_group(group, user):
 
        ugm = UsersGroupMember()
 
        ugm.users_group = group
 
        ugm.user = user
 
        Session.add(ugm)
 
        Session.commit()
 
        return ugm
 

	
 
class Repository(Base, BaseModel):
 
    __tablename__ = 'repositories'
 
    __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},)
 

	
 
    repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
 
    private = Column("private", Boolean(), nullable=True, unique=None, default=None)
 
    enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
 
    enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
 
@@ -505,34 +514,32 @@ class Repository(Base, BaseModel):
 

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

	
 
    @classmethod
 
    def url_sep(cls):
 
        return '/'
 
    
 
    @classmethod
 
    def get_by_repo_name(cls, repo_name):
 
        q = Session.query(cls).filter(cls.repo_name == repo_name)
 

	
 
        q = q.options(joinedload(Repository.fork))\
 
                .options(joinedload(Repository.user))\
 
                .options(joinedload(Repository.group))\
 

	
 
                .options(joinedload(Repository.group))
 
        return q.one()
 

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

	
 
    @classmethod
 
    def base_path(cls):
 
        """
 
        Returns base path when all repos are stored
 
        
 
        :param cls:
 
        """
 
        q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == 
 
                                              cls.url_sep())
 
        q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        return q.one().ui_value
 
@@ -597,25 +604,25 @@ class Repository(Base, BaseModel):
 
        Creates an db based ui object for this repository
 
        """
 
        from mercurial import ui
 
        from mercurial import config
 
        baseui = ui.ui()
 

	
 
        #clean the baseui object
 
        baseui._ocfg = config.config()
 
        baseui._ucfg = config.config()
 
        baseui._tcfg = config.config()
 

	
 

	
 
        ret = Session.query(RhodeCodeUi)\
 
        ret = RhodeCodeUi.query()\
 
            .options(FromCache("sql_cache_short", "repository_repo_ui")).all()
 

	
 
        hg_ui = ret
 
        for ui_ in hg_ui:
 
            if ui_.ui_active:
 
                log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
 
                          ui_.ui_key, ui_.ui_value)
 
                baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
 

	
 
        return baseui
 

	
 
    @classmethod
 
@@ -652,34 +659,34 @@ class Repository(Base, BaseModel):
 

	
 
    #==========================================================================
 
    # SCM CACHE INSTANCE
 
    #==========================================================================
 

	
 
    @property
 
    def invalidate(self):
 
        """
 
        Returns Invalidation object if this repo should be invalidated
 
        None otherwise. `cache_active = False` means that this cache
 
        state is not valid and needs to be invalidated
 
        """
 
        return Session.query(CacheInvalidation)\
 
        return CacheInvalidation.query()\
 
            .filter(CacheInvalidation.cache_key == self.repo_name)\
 
            .filter(CacheInvalidation.cache_active == False)\
 
            .scalar()
 

	
 
    def set_invalidate(self):
 
        """
 
        set a cache for invalidation for this instance
 
        """
 
        inv = Session.query(CacheInvalidation)\
 
        inv = CacheInvalidation.query()\
 
            .filter(CacheInvalidation.cache_key == self.repo_name)\
 
            .scalar()
 

	
 
        if inv is None:
 
            inv = CacheInvalidation(self.repo_name)
 
        inv.cache_active = True
 
        Session.add(inv)
 
        Session.commit()
 

	
 
    @LazyProperty
 
    def scm_instance(self):
 
        return self.__get_instance()
 
@@ -763,26 +770,35 @@ class Group(Base, BaseModel):
 

	
 
        repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
 
                              for x in cls.query().all()])
 
        
 
        repo_groups = sorted(repo_groups,key=lambda t: t[1].split(sep)[0])        
 
        return repo_groups
 
    
 
    @classmethod
 
    def url_sep(cls):
 
        return '/'
 

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

	
 
    @property
 
    def parents(self):
 
        parents_recursion_limit = 5
 
        groups = []
 
        if self.parent_group is None:
 
            return groups
 
        cur_gr = self.parent_group
 
        groups.insert(0, cur_gr)
 
        cnt = 0
 
        while 1:
 
            cnt += 1
 
@@ -792,80 +808,81 @@ class Group(Base, BaseModel):
 
                break
 
            if cnt == parents_recursion_limit:
 
                # this will prevent accidental infinit loops
 
                log.error('group nested more than %s' %
 
                          parents_recursion_limit)
 
                break
 

	
 
            groups.insert(0, gr)
 
        return groups
 

	
 
    @property
 
    def children(self):
 
        return Session.query(Group).filter(Group.parent_group == self)
 
        return Group.query().filter(Group.parent_group == self)
 

	
 
    @property
 
    def name(self):
 
        return self.group_name.split(Group.url_sep())[-1]
 

	
 
    @property
 
    def full_path(self):
 
        return self.group_name
 

	
 
    @property
 
    def full_path_splitted(self):
 
        return self.group_name.split(Group.url_sep())
 

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

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

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

	
 
        return cnt + children_count(self)
 

	
 

	
 
    def get_new_name(self, group_name):
 
        """
 
        returns new full group name based on parent and new name
 
        
 
        :param group_name:
 
        """
 
        path_prefix = self.parent_group.full_path_splitted if self.parent_group else []
 
        path_prefix = (self.parent_group.full_path_splitted if 
 
                       self.parent_group else [])
 
        return Group.url_sep().join(path_prefix + [group_name])
 

	
 

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

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

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

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

	
 
    user = relationship('User')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 
@@ -876,49 +893,49 @@ class UserToPerm(Base, BaseModel):
 
    user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

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

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

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

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

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

	
 

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

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

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

	
 
    users_group = relationship('UsersGroup')
 
    permission = relationship('Permission')
 

	
 

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

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

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

	
 
        new = cls()
 
        new.users_group_id = users_group_id
 
        new.permission = perm
 
@@ -962,25 +979,25 @@ class UsersGroupToPerm(Base, BaseModel):
 
            Session.add(new)
 
            Session.commit()
 
        except:
 
            Session.rollback()
 

	
 

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

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

	
 

	
 
class GroupToPerm(Base, BaseModel):
 
    __tablename__ = 'group_to_perm'
 
    __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing':True})
 

	
 
    group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 
@@ -1014,25 +1031,25 @@ class UserFollowing(Base, BaseModel):
 
    follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
 
    follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 

	
 
    user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
 

	
 
    follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
 
    follows_repository = relationship('Repository', order_by='Repository.repo_name')
 

	
 

	
 
    @classmethod
 
    def get_repo_followers(cls, repo_id):
 
        return Session.query(cls).filter(cls.follows_repo_id == repo_id)
 
        return cls.query().filter(cls.follows_repo_id == repo_id)
 

	
 
class CacheInvalidation(Base, BaseModel):
 
    __tablename__ = 'cache_invalidation'
 
    __table_args__ = (UniqueConstraint('cache_key'), {'extend_existing':True})
 
    cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
 

	
 

	
 
    def __init__(self, cache_key, cache_args=''):
 
        self.cache_key = cache_key
 
@@ -1040,12 +1057,13 @@ class CacheInvalidation(Base, BaseModel)
 
        self.cache_active = False
 

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

	
 
class DbMigrateVersion(Base, BaseModel):
 
    __tablename__ = 'db_migrate_version'
 
    __table_args__ = {'extend_existing':True}
 
    repository_id = Column('repository_id', String(250), primary_key=True)
 
    repository_path = Column('repository_path', Text)
 
    version = Column('version', Integer)
 

	
rhodecode/model/forms.py
Show inline comments
 
@@ -177,36 +177,37 @@ class ValidPassword(formencode.validator
 
                    value['new_password'] = \
 
                        get_crypt_password(value['new_password'])
 
                except UnicodeEncodeError:
 
                    e_dict = {'new_password':_('Invalid characters in password')}
 
                    raise formencode.Invalid('', value, state, error_dict=e_dict)
 

	
 
            return value
 

	
 
class ValidPasswordsMatch(formencode.validators.FancyValidator):
 

	
 
    def validate_python(self, value, state):
 

	
 
        if value['password'] != value['password_confirmation']:
 
        pass_val = value.get('password') or value.get('new_password')
 
        if pass_val != value['password_confirmation']:
 
            e_dict = {'password_confirmation':
 
                   _('Passwords do not match')}
 
            raise formencode.Invalid('', value, state, error_dict=e_dict)
 

	
 
class ValidAuth(formencode.validators.FancyValidator):
 
    messages = {
 
            'invalid_password':_('invalid password'),
 
            'invalid_login':_('invalid user name'),
 
            'disabled_account':_('Your account is disabled')
 
    }
 

	
 
            }
 
    #error mapping
 
    e_dict = {'username':messages['invalid_login'],
 
              'password':messages['invalid_password']}
 
    e_dict_disable = {'username':messages['disabled_account']}
 

	
 
    def validate_python(self, value, state):
 
        password = value['password']
 
        username = value['username']
 
        user = User.get_by_username(username)
 

	
 
        if authenticate(username, password):
 
            return value
 
@@ -244,24 +245,25 @@ def ValidRepoName(edit, old_data):
 
            if slug in [ADMIN_PREFIX, '']:
 
                e_dict = {'repo_name': _('This repository name is disallowed')}
 
                raise formencode.Invalid('', value, state, error_dict=e_dict)
 

	
 

	
 
            if value.get('repo_group'):
 
                gr = Group.get(value.get('repo_group'))
 
                group_path = gr.full_path
 
                # value needs to be aware of group name in order to check
 
                # db key This is an actual just the name to store in the
 
                # database
 
                repo_name_full = group_path + Group.url_sep() + repo_name
 
                
 
            else:
 
                group_path = ''
 
                repo_name_full = repo_name
 

	
 

	
 
            value['repo_name_full'] = repo_name_full
 
            rename = old_data.get('repo_name') != repo_name_full
 
            create = not edit
 
            if  rename or create:
 

	
 
                if group_path != '':
 
                    if RepoModel().get_by_repo_name(repo_name_full,):
 
@@ -487,45 +489,46 @@ class LoginForm(formencode.Schema):
 
                                'tooShort':_('Enter a value %(min)i characters long or more')}
 
                            )
 

	
 
    password = UnicodeString(
 
                            strip=True,
 
                            min=3,
 
                            not_empty=True,
 
                            messages={
 
                                'empty':_('Please enter a password'),
 
                                'tooShort':_('Enter %(min)i characters or more')}
 
                                )
 

	
 

	
 
    #chained validators have access to all data
 
    chained_validators = [ValidAuth]
 

	
 
def UserForm(edit=False, old_data={}):
 
    class _UserForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = True
 
        username = All(UnicodeString(strip=True, min=1, not_empty=True),
 
                       ValidUsername(edit, old_data))
 
        if edit:
 
            new_password = All(UnicodeString(strip=True, min=6, not_empty=False))
 
            password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=False))
 
            admin = StringBoolean(if_missing=False)
 
        else:
 
            password = All(UnicodeString(strip=True, min=6, not_empty=True))
 
            password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=False))
 
            
 
        active = StringBoolean(if_missing=False)
 
        name = UnicodeString(strip=True, min=1, not_empty=True)
 
        lastname = UnicodeString(strip=True, min=1, not_empty=True)
 
        email = All(Email(not_empty=True), UniqSystemEmail(old_data))
 

	
 
        chained_validators = [ValidPassword]
 
        chained_validators = [ValidPasswordsMatch, ValidPassword]
 

	
 
    return _UserForm
 

	
 

	
 
def UsersGroupForm(edit=False, old_data={}, available_members=[]):
 
    class _UsersGroupForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = True
 

	
 
        users_group_name = All(UnicodeString(strip=True, min=1, not_empty=True),
 
                       ValidUsersGroup(edit, old_data))
 

	
 
@@ -607,34 +610,37 @@ def RepoForkForm(edit=False, old_data={}
 
        allow_extra_fields = True
 
        filter_extra_fields = False
 
        fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
 
                        SlugifyName())
 
        description = UnicodeString(strip=True, min=1, not_empty=True)
 
        private = StringBoolean(if_missing=False)
 
        repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
 

	
 
        chained_validators = [ValidForkName()]
 

	
 
    return _RepoForkForm
 

	
 
def RepoSettingsForm(edit=False, old_data={}):
 
def RepoSettingsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
 
                     repo_groups=[]):
 
    class _RepoForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = False
 
        repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
 
                        SlugifyName())
 
        description = UnicodeString(strip=True, min=1, not_empty=True)
 
        repo_group = OneOf(repo_groups, hideList=True)
 
        private = StringBoolean(if_missing=False)
 

	
 
        chained_validators = [ValidRepoName(edit, old_data), ValidPerms, ValidSettings]
 
        chained_validators = [ValidRepoName(edit, old_data), ValidPerms, 
 
                              ValidSettings]
 
    return _RepoForm
 

	
 

	
 
def ApplicationSettingsForm():
 
    class _ApplicationSettingsForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = False
 
        rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
 
        rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
 
        rhodecode_ga_code = UnicodeString(strip=True, min=1, not_empty=False)
 

	
 
    return _ApplicationSettingsForm
rhodecode/model/repo.py
Show inline comments
 
@@ -85,24 +85,64 @@ class RepoModel(BaseModel):
 
    def get_users_groups_js(self):
 
        users_groups = self.sa.query(UsersGroup)\
 
            .filter(UsersGroup.users_group_active == True).all()
 

	
 
        g_tmpl = '''{id:%s, grname:"%s",grmembers:"%s"},'''
 

	
 
        users_groups_array = '[%s]' % '\n'.join([g_tmpl % \
 
                                    (gr.users_group_id, gr.users_group_name,
 
                                     len(gr.members))
 
                                        for gr in users_groups])
 
        return users_groups_array
 

	
 
    def _get_defaults(self, repo_name):
 
        """
 
        Get's information about repository, and returns a dict for 
 
        usage in forms
 
        
 
        :param repo_name:
 
        """
 

	
 
        repo_info = Repository.get_by_repo_name(repo_name)
 

	
 
        if repo_info is None:
 
            return None
 

	
 
        defaults = repo_info.get_dict()
 
        group, repo_name = repo_info.groups_and_repo
 
        defaults['repo_name'] = repo_name
 
        defaults['repo_group'] = getattr(group[-1] if group else None,
 
                                         'group_id', None)
 

	
 
        # fill owner
 
        if repo_info.user:
 
            defaults.update({'user': repo_info.user.username})
 
        else:
 
            replacement_user = User.query().filter(User.admin ==
 
                                                   True).first().username
 
            defaults.update({'user': replacement_user})
 

	
 
        # fill repository users
 
        for p in repo_info.repo_to_perm:
 
            defaults.update({'u_perm_%s' % p.user.username:
 
                             p.permission.permission_name})
 

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

	
 
        return defaults
 

	
 

	
 
    def update(self, repo_name, form_data):
 
        try:
 
            cur_repo = self.get_by_repo_name(repo_name, cache=False)
 

	
 
            # update permissions
 
            for member, perm, member_type in form_data['perms_updates']:
 
                if member_type == 'user':
 
                    r2p = self.sa.query(RepoToPerm)\
 
                            .filter(RepoToPerm.user == User.get_by_username(member))\
 
                            .filter(RepoToPerm.repository == cur_repo)\
 
                            .one()
 

	
 
@@ -142,25 +182,25 @@ class RepoModel(BaseModel):
 
                                        .filter(Permission.
 
                                                permission_name == perm)\
 
                                                .scalar()
 
                    self.sa.add(g2p)
 

	
 
            # update current repo
 
            for k, v in form_data.items():
 
                if k == 'user':
 
                    cur_repo.user = User.get_by_username(v)
 
                elif k == 'repo_name':
 
                    pass
 
                elif k == 'repo_group':
 
                    cur_repo.group_id = v
 
                    cur_repo.group = Group.get(v)
 

	
 
                else:
 
                    setattr(cur_repo, k, v)
 

	
 
            new_name = cur_repo.get_new_name(form_data['repo_name'])
 
            cur_repo.repo_name = new_name
 

	
 
            self.sa.add(cur_repo)
 

	
 
            if repo_name != new_name:
 
                # rename repository
 
                self.__rename_repo(old=repo_name, new=new_name)
 
@@ -359,12 +399,13 @@ class RepoModel(BaseModel):
 
        """
 
        rm_path = os.path.join(self.repos_path, repo.repo_name)
 
        log.info("Removing %s", rm_path)
 
        #disable hg/git
 
        alias = repo.repo_type
 
        shutil.move(os.path.join(rm_path, '.%s' % alias),
 
                    os.path.join(rm_path, 'rm__.%s' % alias))
 
        #disable repo
 
        shutil.move(rm_path, os.path.join(self.repos_path, 'rm__%s__%s' \
 
                                          % (datetime.today()\
 
                                             .strftime('%Y%m%d_%H%M%S_%f'),
 
                                            repo.repo_name)))
 

	
rhodecode/model/repo_permission.py
Show inline comments
 
new file 100644
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.model.users_group
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    repository permission model for RhodeCode
 

	
 
    :created_on: Oct 1, 2011
 
    :author: nvinot
 
    :copyright: (C) 2011-2011 Nicolas Vinot <aeris@imirhil.fr>
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# 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/>.
 

	
 
import logging
 
from rhodecode.model.db import BaseModel, RepoToPerm, Permission
 
from rhodecode.model.meta import Session
 

	
 
log = logging.getLogger(__name__)
 

	
 
class RepositoryPermissionModel(BaseModel):
 
    def get_user_permission(self, repository, user):
 
        return RepoToPerm.query() \
 
                .filter(RepoToPerm.user == user) \
 
                .filter(RepoToPerm.repository == repository) \
 
                .scalar()
 

	
 
    def update_user_permission(self, repository, user, permission):
 
        permission = Permission.get_by_key(permission)
 
        current = self.get_user_permission(repository, user)
 
        if current:
 
            if not current.permission is permission:
 
                current.permission = permission
 
        else:
 
            p = RepoToPerm()
 
            p.user = user
 
            p.repository = repository
 
            p.permission = permission
 
            Session.add(p)
 
        Session.commit()
 

	
 
    def delete_user_permission(self, repository, user):
 
        current = self.get_user_permission(repository, user)
 
        if current:
 
            Session.delete(current)
 
            Session.commit()
 

	
 
    def update_or_delete_user_permission(self, repository, user, permission):
 
        if permission:
 
            self.update_user_permission(repository, user, permission)
 
        else:
 
            self.delete_user_permission(repository, user)
rhodecode/model/user.py
Show inline comments
 
@@ -40,25 +40,24 @@ from sqlalchemy.exc import DatabaseError
 
from rhodecode.lib import generate_api_key
 
from sqlalchemy.orm import joinedload
 

	
 
log = logging.getLogger(__name__)
 

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

	
 

	
 
class UserModel(BaseModel):
 

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

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

	
 
        if case_insensitive:
 
            user = self.sa.query(User).filter(User.username.ilike(username))
 
        else:
 
@@ -78,33 +77,35 @@ class UserModel(BaseModel):
 
                                          "get_user_%s" % api_key))
 
        return user.scalar()
 

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

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

	
 
    def create_ldap(self, username, password, user_dn, attrs):
 
        """
 
        Checks if user is in database, if not creates this user marked
 
        as ldap user
 
        
 
        :param username:
 
        :param password:
 
        :param user_dn:
 
        :param attrs:
 
        """
 
        from rhodecode.lib.auth import get_crypt_password
 
        log.debug('Checking for such ldap account in RhodeCode database')
 
        if self.get_by_username(username, case_insensitive=True) is None:
 
            try:
 
                new_user = User()
 
                # add ldap account always lowercase
 
                new_user.username = username.lower()
 
@@ -377,12 +378,13 @@ class UserModel(BaseModel):
 
            for perm in user_repo_perms_from_users_groups:
 
                p = perm.Permission.permission_name
 
                cur_perm = user.permissions['repositories'][perm.
 
                                                    UsersGroupRepoToPerm.
 
                                                    repository.repo_name]
 
                #overwrite permission only if it's greater than permission
 
                # given from other sources
 
                if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
 
                    user.permissions['repositories'][perm.UsersGroupRepoToPerm.
 
                                                     repository.repo_name] = p
 

	
 
        return user
 

	
rhodecode/model/users_group.py
Show inline comments
 
new file 100644
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.model.users_group
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    users group model for RhodeCode
 

	
 
    :created_on: Oct 1, 2011
 
    :author: nvinot
 
    :copyright: (C) 2011-2011 Nicolas Vinot <aeris@imirhil.fr>
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# 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/>.
 

	
 
import logging
 
import traceback
 

	
 
from rhodecode.model import BaseModel
 
from rhodecode.model.caching_query import FromCache
 
from rhodecode.model.db import UsersGroupMember, UsersGroup
 

	
 
log = logging.getLogger(__name__)
 

	
 
class UsersGroupModel(BaseModel):
 

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

	
 
    def get_by_name(self, name, cache = False, case_insensitive = False):
 
        users_group = UsersGroup.query()
 
        if case_insensitive:
 
            users_group = users_group.filter(UsersGroup.users_group_name.ilike(name))
 
        else:
 
            users_group = users_group.filter(UsersGroup.users_group_name == name)
 
        if cache:
 
            users_group = users_group.options(FromCache("sql_cache_short",
 
                                          "get_users_group_%s" % name))
 
        return users_group.scalar()
 

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

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

	
 
    def add_user_to_group(self, users_group, user):
 
        for m in users_group.members:
 
            u = m.user
 
            if u.user_id == user.user_id:
 
                return m
 

	
 
        try:
 
            users_group_member = UsersGroupMember()
 
            users_group_member.user = user
 
            users_group_member.users_group = users_group
 

	
 
            users_group.members.append(users_group_member)
 
            user.group_member.append(users_group_member)
 

	
 
            self.sa.add(users_group_member)
 
            self.sa.commit()
 
            return users_group_member
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
rhodecode/templates/admin/repos_groups/repos_groups_add.html
Show inline comments
 
@@ -20,43 +20,43 @@
 
<div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}       
 
    </div>
 
    <!-- end box / title -->
 
    ${h.form(url('repos_groups'))}
 
    <div class="form">
 
        <!-- fields -->
 
        <div class="fields">
 
             <div class="field">
 
                <div class="label">
 
                    <label for="users_group_name">${_('Group name')}:</label>
 
                    <label for="group_name">${_('Group name')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.text('group_name',class_='medium')}
 
                </div>
 
             </div>
 
             
 
            <div class="field">
 
                <div class="label label-textarea">
 
                    <label for="description">${_('Description')}:</label>
 
                    <label for="group_description">${_('Description')}:</label>
 
                </div>
 
                <div class="textarea text-area editor">
 
                    ${h.textarea('group_description',cols=23,rows=5,class_="medium")}
 
                </div>
 
             </div>
 
             
 
             <div class="field">
 
                 <div class="label">
 
                     <label for="repo_group">${_('Group parent')}:</label>
 
                     <label for="group_parent_id">${_('Group parent')}:</label>
 
                 </div>
 
                 <div class="input">
 
                     ${h.select('group_parent_id','',c.repo_groups,class_="medium")}
 
                 </div>
 
             </div>            
 
                         
 
            <div class="buttons">
 
              ${h.submit('save',_('save'),class_="ui-button")}
 
            </div>             
 
        </div>
 
    </div>
 
    ${h.end_form()}
rhodecode/templates/admin/repos_groups/repos_groups_edit.html
Show inline comments
 
@@ -20,43 +20,43 @@
 
<div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}       
 
    </div>
 
    <!-- end box / title -->
 
    ${h.form(url('repos_group',id=c.repos_group.group_id),method='put')}
 
    <div class="form">
 
        <!-- fields -->
 
        <div class="fields">
 
             <div class="field">
 
                <div class="label">
 
                    <label for="users_group_name">${_('Group name')}:</label>
 
                    <label for="group_name">${_('Group name')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.text('group_name',class_='medium')}
 
                </div>
 
             </div>
 
             
 
	        <div class="field">
 
	            <div class="label label-textarea">
 
	                <label for="description">${_('Description')}:</label>
 
	                <label for="group_description">${_('Description')}:</label>
 
	            </div>
 
	            <div class="textarea text-area editor">
 
	                ${h.textarea('group_description',cols=23,rows=5,class_="medium")}
 
	            </div>
 
	         </div>
 
             
 
	         <div class="field">
 
	             <div class="label">
 
	                 <label for="repo_group">${_('Group parent')}:</label>
 
	                 <label for="group_parent_id">${_('Group parent')}:</label>
 
	             </div>
 
	             <div class="input">
 
	                 ${h.select('group_parent_id','',c.repo_groups,class_="medium")}
 
	             </div>
 
	         </div>             
 
                         
 
            <div class="buttons">
 
              ${h.submit('save',_('save'),class_="ui-button")}
 
            </div>             
 
        </div>
 
    </div>
 
    ${h.end_form()}
rhodecode/templates/admin/settings/settings.html
Show inline comments
 
@@ -25,52 +25,52 @@
 
    ${h.form(url('admin_setting', setting_id='mapping'),method='put')}
 
    <div class="form">
 
        <!-- fields -->
 
        
 
        <div class="fields">
 
			<div class="field">
 
		        <div class="label label-checkbox">
 
		            <label for="destroy">${_('rescan option')}:</label>
 
		        </div>
 
		        <div class="checkboxes">
 
		            <div class="checkbox">
 
		                ${h.checkbox('destroy',True)}
 
		                <label for="checkbox-1">
 
		                <label for="destroy">
 
		                <span class="tooltip" title="${h.tooltip(_('In case a repository was deleted from filesystem and there are leftovers in the database check this option to scan obsolete data in database and remove it.'))}">
 
		                ${_('destroy old data')}</span> </label>
 
		            </div>
 
		        </div>
 
			</div>
 
                            
 
            <div class="buttons">
 
            ${h.submit('rescan',_('Rescan repositories'),class_="ui-button")}
 
            </div>                                                          
 
        </div>
 
    </div>  
 
    ${h.end_form()}
 
    
 
    <h3>${_('Whoosh indexing')}</h3>
 
    ${h.form(url('admin_setting', setting_id='whoosh'),method='put')}
 
    <div class="form">
 
        <!-- fields -->
 
        
 
        <div class="fields">
 
            <div class="field">
 
                <div class="label label-checkbox">
 
                    <label for="destroy">${_('index build option')}:</label>
 
                    <label>${_('index build option')}:</label>
 
                </div>
 
                <div class="checkboxes">
 
                    <div class="checkbox">
 
                        ${h.checkbox('full_index',True)}
 
                        <label for="checkbox-1">${_('build from scratch')}</label>
 
                        <label for="full_index">${_('build from scratch')}</label>
 
                    </div>
 
                </div>
 
            </div>
 
                            
 
            <div class="buttons">
 
            ${h.submit('reindex',_('Reindex'),class_="ui-button")}
 
            </div>                                                          
 
        </div>
 
    </div>  
 
    ${h.end_form()}
 
         
 
    <h3>${_('Global application settings')}</h3> 
 
@@ -91,61 +91,61 @@
 
                          
 
            <div class="field">
 
                <div class="label">
 
                    <label for="rhodecode_realm">${_('Realm text')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.text('rhodecode_realm',size=30)}
 
                </div>
 
            </div>
 
            
 
            <div class="field">
 
                <div class="label">
 
                    <label for="ga_code">${_('GA code')}:</label>
 
                    <label for="rhodecode_ga_code">${_('GA code')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.text('rhodecode_ga_code',size=30)}
 
                </div>
 
            </div>
 
                                                 
 
            <div class="buttons">
 
                ${h.submit('save',_('Save settings'),class_="ui-button")}
 
                ${h.reset('reset',_('Reset'),class_="ui-button")}
 
           </div>                                                          
 
        </div>
 
    </div>      
 
    ${h.end_form()}
 

	
 
    <h3>${_('Mercurial settings')}</h3> 
 
    ${h.form(url('admin_setting', setting_id='mercurial'),method='put')}
 
    <div class="form">
 
        <!-- fields -->
 
        
 
        <div class="fields">
 
             
 
             <div class="field">
 
                <div class="label label-checkbox">
 
                    <label for="web_push_ssl">${_('Web')}:</label>
 
                    <label>${_('Web')}:</label>
 
                </div>
 
                <div class="checkboxes">
 
					<div class="checkbox">
 
						${h.checkbox('web_push_ssl','true')}
 
						<label for="web_push_ssl">${_('require ssl for pushing')}</label>
 
					</div>
 
				</div>
 
             </div>						
 

	
 
             <div class="field">
 
                <div class="label label-checkbox">
 
                    <label for="web_push_ssl">${_('Hooks')}:</label>
 
                    <label>${_('Hooks')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.link_to(_('advanced setup'),url('admin_edit_setting',setting_id='hooks'))}
 
                </div>                
 
                <div class="checkboxes">
 
					<div class="checkbox">
 
						${h.checkbox('hooks_changegroup_update','True')}
 
						<label for="hooks_changegroup_update">${_('Update repository after push (hg update)')}</label>
 
					</div>
 
					<div class="checkbox">
 
						${h.checkbox('hooks_changegroup_repo_size','True')}
 
						<label for="hooks_changegroup_repo_size">${_('Show repository size after push')}</label>
rhodecode/templates/admin/users/user_add.html
Show inline comments
 
@@ -38,24 +38,33 @@
 
            
 
             <div class="field">
 
                <div class="label">
 
                    <label for="password">${_('Password')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.password('password',class_='small')}
 
                </div>
 
             </div>
 
            
 
             <div class="field">
 
                <div class="label">
 
                    <label for="password_confirmation">${_('Password confirmation')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.password('password_confirmation',class_="small",autocomplete="off")}
 
                </div>
 
             </div>    
 
                         
 
             <div class="field">
 
                <div class="label">
 
                    <label for="name">${_('First Name')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.text('name',class_='small')}
 
                </div>
 
             </div>
 
            
 
             <div class="field">
 
                <div class="label">
 
                    <label for="lastname">${_('Last Name')}:</label>
 
                </div>
 
                <div class="input">
rhodecode/templates/admin/users/user_edit.html
Show inline comments
 
@@ -62,24 +62,33 @@
 
            
 
             <div class="field">
 
                <div class="label">
 
                    <label for="new_password">${_('New password')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.password('new_password',class_='medium',autocomplete="off")}
 
                </div>
 
             </div>
 
            
 
             <div class="field">
 
                <div class="label">
 
                    <label for="password_confirmation">${_('New password confirmation')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.password('password_confirmation',class_="medium",autocomplete="off")}
 
                </div>
 
             </div>
 
                         
 
             <div class="field">
 
                <div class="label">
 
                    <label for="name">${_('First Name')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.text('name',class_='medium')}
 
                </div>
 
             </div>
 
            
 
             <div class="field">
 
                <div class="label">
 
                    <label for="lastname">${_('Last Name')}:</label>
 
                </div>
 
                <div class="input">
 
@@ -123,25 +132,25 @@
 
</div>
 
<div class="box box-right">
 
    <!-- box / title -->
 
    <div class="title">
 
        <h5>${_('Permissions')}</h5>       
 
    </div>
 
    ${h.form(url('user_perm', id=c.user.user_id),method='put')}
 
    <div class="form">
 
        <!-- fields -->
 
        <div class="fields">
 
             <div class="field">
 
                <div class="label label-checkbox">
 
                    <label for="">${_('Create repositories')}:</label>
 
                    <label for="create_repo_perm">${_('Create repositories')}:</label>
 
                </div>
 
                <div class="checkboxes">
 
                    ${h.checkbox('create_repo_perm',value=True)}
 
                </div>
 
             </div>
 
            <div class="buttons">
 
              ${h.submit('save',_('Save'),class_="ui-button")}
 
              ${h.reset('reset',_('Reset'),class_="ui-button")}
 
            </div>             
 
        </div>    
 
    </div>
 
    ${h.end_form()}    
rhodecode/templates/admin/users/user_edit_my_account.html
Show inline comments
 
@@ -51,24 +51,33 @@
 
	            
 
	             <div class="field">
 
	                <div class="label">
 
	                    <label for="new_password">${_('New password')}:</label>
 
	                </div>
 
	                <div class="input">
 
	                    ${h.password('new_password',class_="medium",autocomplete="off")}
 
	                </div>
 
	             </div>
 
	            
 
	             <div class="field">
 
	                <div class="label">
 
                        <label for="password_confirmation">${_('New password confirmation')}:</label>
 
                    </div>
 
                    <div class="input">
 
                        ${h.password('password_confirmation',class_="medium",autocomplete="off")}
 
                    </div>
 
                 </div>
 
                 	            
 
	             <div class="field">
 
	                <div class="label">
 
	                    <label for="name">${_('First Name')}:</label>
 
	                </div>
 
	                <div class="input">
 
	                    ${h.text('name',class_="medium")}
 
	                </div>
 
	             </div>
 
	            
 
	             <div class="field">
 
	                <div class="label">
 
	                    <label for="lastname">${_('Last Name')}:</label>
 
	                </div>
 
	                <div class="input">
 
@@ -145,28 +154,30 @@
 
		            %endif		            
 
		            </td> 
 
		            <td><span class="tooltip" title="${repo['last_change']}">${("r%s:%s") % (repo['rev'],h.short_id(repo['tip']))}</span></td>
 
		            <td><a href="${h.url('repo_settings_home',repo_name=repo['name'])}" title="${_('edit')}"><img class="icon" alt="${_('private')}" src="${h.url('/images/icons/application_form_edit.png')}"/></a></td>
 
		            <td>
 
	                  ${h.form(url('repo_settings_delete', repo_name=repo['name']),method='delete')}
 
	                    ${h.submit('remove_%s' % repo['name'],'',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
 
	                  ${h.end_form()}	            
 
		            </td>
 
		        </tr>
 
		     %endfor
 
	     %else:
 
            <div style="padding:5px 0px 10px 0px;">
 
	     	${_('No repositories yet')} 
 
	     	%if h.HasPermissionAny('hg.admin','hg.create.repository')():
 
	     		${h.link_to(_('create one now'),h.url('admin_settings_create_repository'))}
 
	     		${h.link_to(_('create one now'),h.url('admin_settings_create_repository'),class_="ui-button-small")}
 
	     	%endif
 
            </div>
 
	     %endif
 
	     </tbody>
 
	     </table>
 
    </div>
 
    
 
</div>
 
    <script type="text/javascript">
 
     var D = YAHOO.util.Dom;
 
     var E = YAHOO.util.Event;
 
     var S = YAHOO.util.Selector;
 
     
 
     var q_filter = D.get('q_filter');
rhodecode/templates/admin/users_groups/users_group_edit.html
Show inline comments
 
@@ -244,25 +244,25 @@ ${h.end_form()}
 
</script>    
 
<div class="box box-right">
 
    <!-- box / title -->
 
    <div class="title">
 
        <h5>${_('Permissions')}</h5>       
 
    </div>
 
    ${h.form(url('users_group_perm', id=c.users_group.users_group_id), method='put')}
 
    <div class="form">
 
        <!-- fields -->
 
        <div class="fields">
 
             <div class="field">
 
                <div class="label label-checkbox">
 
                    <label for="">${_('Create repositories')}:</label>
 
                    <label for="create_repo_perm">${_('Create repositories')}:</label>
 
                </div>
 
                <div class="checkboxes">
 
                    ${h.checkbox('create_repo_perm',value=True)}
 
                </div>
 
             </div>
 
            <div class="buttons">
 
              ${h.submit('save',_('Save'),class_="ui-button")}
 
              ${h.reset('reset',_('Reset'),class_="ui-button")}
 
            </div>             
 
        </div>    
 
    </div>
 
    ${h.end_form()}    
rhodecode/templates/settings/repo_settings.html
Show inline comments
 
@@ -25,25 +25,32 @@
 
    ${h.form(url('repo_settings_update', repo_name=c.repo_info.repo_name),method='put')}
 
    <div class="form">
 
        <!-- fields -->
 
        <div class="fields">
 
            <div class="field">
 
                <div class="label">
 
                    <label for="repo_name">${_('Name')}:</label>
 
                </div>
 
                <div class="input input-medium">
 
                    ${h.text('repo_name',class_="small")}
 
                </div>
 
             </div>
 
             
 
            <div class="field">
 
                <div class="label">
 
                    <label for="repo_group">${_('Repository group')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.select('repo_group','',c.repo_groups,class_="medium")}
 
                </div>
 
            </div>             
 
            <div class="field">
 
                <div class="label label-textarea">
 
                    <label for="description">${_('Description')}:</label>
 
                </div>
 
                <div class="textarea text-area editor">
 
                    ${h.textarea('description',cols=23,rows=5)}
 
                </div>
 
            </div>
 
            
 
            <div class="field">
 
                <div class="label label-checkbox">
 
                    <label for="private">${_('Private')}:</label>
rhodecode/tests/__init__.py
Show inline comments
 
@@ -68,18 +68,16 @@ class TestController(TestCase):
 
                 password=TEST_USER_ADMIN_PASS):
 
        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')
 
        self.assertEqual(response.session['rhodecode_user'].username, username)
 
        return response.follow()
 

	
 

	
 

	
 
    def checkSessionFlash(self, response, msg):
 
        self.assertTrue('flash' in response.session)
 
        self.assertTrue(msg in response.session['flash'][0][1])
 

	
rhodecode/tests/functional/test_admin_settings.py
Show inline comments
 
@@ -128,47 +128,49 @@ class TestAdminSettingsController(TestCo
 
        self.log_user()
 

	
 
        new_email = 'new@mail.pl'
 
        new_name = 'NewName'
 
        new_lastname = 'NewLastname'
 
        new_password = 'test123'
 

	
 

	
 
        response = self.app.post(url('admin_settings_my_account_update'),
 
                                 params=dict(_method='put',
 
                                             username='test_admin',
 
                                             new_password=new_password,
 
                                             password_confirmation = new_password,
 
                                             password='',
 
                                             name=new_name,
 
                                             lastname=new_lastname,
 
                                             email=new_email,))
 
        response.follow()
 

	
 
        assert 'Your account was updated successfully' in response.session['flash'][0][1], 'no flash message about success of change'
 
        user = self.sa.query(User).filter(User.username == 'test_admin').one()
 
        assert user.email == new_email , 'incorrect user email after update got %s vs %s' % (user.email, new_email)
 
        assert user.name == new_name, 'updated field mismatch %s vs %s' % (user.name, new_name)
 
        assert user.lastname == new_lastname, 'updated field mismatch %s vs %s' % (user.lastname, new_lastname)
 
        assert check_password(new_password, user.password) is True, 'password field mismatch %s vs %s' % (user.password, new_password)
 

	
 
        #bring back the admin settings
 
        old_email = 'test_admin@mail.com'
 
        old_name = 'RhodeCode'
 
        old_lastname = 'Admin'
 
        old_password = 'test12'
 

	
 
        response = self.app.post(url('admin_settings_my_account_update'), params=dict(
 
                                                            _method='put',
 
                                                            username='test_admin',
 
                                                            new_password=old_password,
 
                                                            password_confirmation = old_password,
 
                                                            password='',
 
                                                            name=old_name,
 
                                                            lastname=old_lastname,
 
                                                            email=old_email,))
 

	
 
        response.follow()
 
        self.checkSessionFlash(response,
 
                               'Your account was updated successfully')
 

	
 
        user = self.sa.query(User).filter(User.username == 'test_admin').one()
 
        assert user.email == old_email , 'incorrect user email after update got %s vs %s' % (user.email, old_email)
 

	
 
@@ -177,32 +179,34 @@ class TestAdminSettingsController(TestCo
 
        assert user.lastname == old_lastname, 'updated field mismatch %s vs %s' % (user.lastname, old_lastname)
 
        assert check_password(old_password, user.password) is True , 'password updated field mismatch %s vs %s' % (user.password, old_password)
 

	
 

	
 
    def test_my_account_update_err_email_exists(self):
 
        self.log_user()
 

	
 
        new_email = 'test_regular@mail.com'#already exisitn email
 
        response = self.app.post(url('admin_settings_my_account_update'), params=dict(
 
                                                            _method='put',
 
                                                            username='test_admin',
 
                                                            new_password='test12',
 
                                                            password_confirmation = 'test122',
 
                                                            name='NewName',
 
                                                            lastname='NewLastname',
 
                                                            email=new_email,))
 

	
 
        assert 'This e-mail address is already taken' in response.body, 'Missing error message about existing email'
 

	
 

	
 
    def test_my_account_update_err(self):
 
        self.log_user('test_regular2', 'test12')
 

	
 
        new_email = 'newmail.pl'
 
        response = self.app.post(url('admin_settings_my_account_update'), params=dict(
 
                                                            _method='put',
 
                                                            username='test_admin',
 
                                                            new_password='test12',
 
                                                            password_confirmation = 'test122',
 
                                                            name='NewName',
 
                                                            lastname='NewLastname',
 
                                                            email=new_email,))
 
        assert 'An email address must contain a single @' in response.body, 'Missing error message about wrong email'
 
        assert 'This username already exists' in response.body, 'Missing error message about existing user'
rhodecode/tests/functional/test_admin_users.py
Show inline comments
 
@@ -7,30 +7,32 @@ class TestAdminUsersController(TestContr
 

	
 
    def test_index(self):
 
        response = self.app.get(url('users'))
 
        # Test response...
 

	
 
    def test_index_as_xml(self):
 
        response = self.app.get(url('formatted_users', format='xml'))
 

	
 
    def test_create(self):
 
        self.log_user()
 
        username = 'newtestuser'
 
        password = 'test12'
 
        password_confirmation = password
 
        name = 'name'
 
        lastname = 'lastname'
 
        email = 'mail@mail.com'
 

	
 
        response = self.app.post(url('users'), {'username':username,
 
                                               'password':password,
 
                                               'password_confirmation':password_confirmation,
 
                                               'name':name,
 
                                               'active':True,
 
                                               'lastname':lastname,
 
                                               'email':email})
 

	
 

	
 
        assert '''created user %s''' % (username) in response.session['flash'][0], 'No flash message about new user'
 

	
 
        new_user = self.sa.query(User).filter(User.username == username).one()
 

	
 

	
 
        assert new_user.username == username, 'wrong info about username'
 
@@ -81,24 +83,25 @@ class TestAdminUsersController(TestContr
 
        response = self.app.post(url('user', id=1), params=dict(_method='put'))
 

	
 
    def test_delete(self):
 
        self.log_user()
 
        username = 'newtestuserdeleteme'
 
        password = 'test12'
 
        name = 'name'
 
        lastname = 'lastname'
 
        email = 'todeletemail@mail.com'
 

	
 
        response = self.app.post(url('users'), {'username':username,
 
                                               'password':password,
 
                                               'password_confirmation':password,
 
                                               'name':name,
 
                                               'active':True,
 
                                               'lastname':lastname,
 
                                               'email':email})
 

	
 
        response = response.follow()
 

	
 
        new_user = self.sa.query(User).filter(User.username == username).one()
 
        response = self.app.delete(url('user', id=new_user.user_id))
 

	
 
        assert """successfully deleted user""" in response.session['flash'][0], 'No info about user deletion'
 

	
rhodecode/tests/test_hg_operations.py
Show inline comments
 
@@ -39,36 +39,40 @@ from pylons import config
 
from sqlalchemy import engine_from_config
 

	
 
from rhodecode.lib.utils import add_cache
 
from rhodecode.model import init_model
 
from rhodecode.model import meta
 
from rhodecode.model.db import User, Repository, UserLog
 
from rhodecode.lib.auth import get_crypt_password
 

	
 
from rhodecode.tests import TESTS_TMP_PATH, NEW_HG_REPO, HG_REPO
 
from rhodecode.config.environment import load_environment
 

	
 
rel_path = dn(dn(dn(os.path.abspath(__file__))))
 
conf = appconfig('config:development.ini', relative_to=rel_path)
 

	
 
conf = appconfig('config:%s' % sys.argv[1], relative_to=rel_path)
 
load_environment(conf.global_conf, conf.local_conf)
 

	
 
add_cache(conf)
 

	
 
USER = 'test_admin'
 
PASS = 'test12'
 
HOST = '127.0.0.1:5000'
 
DEBUG = True if sys.argv[1:] else False
 
DEBUG = False
 
print 'DEBUG:', DEBUG
 
log = logging.getLogger(__name__)
 

	
 
engine = engine_from_config(conf, 'sqlalchemy.db1.')
 
init_model(engine)
 
sa = meta.Session
 

	
 
class Command(object):
 

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

	
 
    def execute(self, cmd, *args):
 
        """Runs command on the system with given ``args``.
 
        """
 

	
 
        command = cmd + ' ' + ' '.join(args)
 
        log.debug('Executing %s' % command)
 
@@ -87,100 +91,87 @@ def test_wrapp(func):
 
        print '>>>%s' % func.__name__
 
        try:
 
            res = func(*args, **kwargs)
 
        except Exception, e:
 
            print ('###############\n-'
 
                   '--%s failed %s--\n'
 
                   '###############\n' % (func.__name__, e))
 
            sys.exit()
 
        print '++OK++'
 
        return res
 
    return __wrapp
 

	
 
def get_session():
 
    engine = engine_from_config(conf, 'sqlalchemy.db1.')
 
    init_model(engine)
 
    sa = meta.Session
 
    return sa
 

	
 

	
 
def create_test_user(force=True):
 
    print '\tcreating test user'
 
    sa = get_session()
 

	
 
    user = sa.query(User).filter(User.username == USER).scalar()
 
    user = User.get_by_username(USER)
 

	
 
    if force and user is not None:
 
        print '\tremoving current user'
 
        for repo in sa.query(Repository).filter(Repository.user == user).all():
 
        for repo in Repository.query().filter(Repository.user == user).all():
 
            sa.delete(repo)
 
        sa.delete(user)
 
        sa.commit()
 

	
 
    if user is None or force:
 
        print '\tcreating new one'
 
        new_usr = User()
 
        new_usr.username = USER
 
        new_usr.password = get_crypt_password(PASS)
 
        new_usr.email = 'mail@mail.com'
 
        new_usr.name = 'test'
 
        new_usr.lastname = 'lasttestname'
 
        new_usr.active = True
 
        new_usr.admin = True
 
        sa.add(new_usr)
 
        sa.commit()
 

	
 
    print '\tdone'
 

	
 

	
 
def create_test_repo(force=True):
 
    from rhodecode.model.repo import RepoModel
 
    sa = get_session()
 

	
 
    user = sa.query(User).filter(User.username == USER).scalar()
 
    user = User.get_by_username(USER)
 
    if user is None:
 
        raise Exception('user not found')
 

	
 

	
 
    repo = sa.query(Repository).filter(Repository.repo_name == HG_REPO).scalar()
 

	
 
    if repo is None:
 
        print '\trepo not found creating'
 

	
 
        form_data = {'repo_name':HG_REPO,
 
                     'repo_type':'hg',
 
                     'private':False,
 
                     'clone_uri':'' }
 
        rm = RepoModel(sa)
 
        rm.base_path = '/home/hg'
 
        rm.create(form_data, user)
 

	
 

	
 
def set_anonymous_access(enable=True):
 
    sa = get_session()
 
    user = sa.query(User).filter(User.username == 'default').one()
 
    sa.expire(user)
 
    user = User.get_by_username('default')
 
    user.active = enable
 
    sa.add(user)
 
    sa.commit()
 
    sa.remove()
 
    import time;time.sleep(3)
 
    print '\tanonymous access is now:', enable
 

	
 
    if enable != User.get_by_username('default').active:
 
        raise Exception('Cannot set anonymous access')
 

	
 
def get_anonymous_access():
 
    sa = get_session()
 
    obj1 = sa.query(User).filter(User.username == 'default').one()
 
    sa.expire(obj1)
 
    return obj1.active
 
    user = User.get_by_username('default')
 
    return user.active
 

	
 

	
 
#==============================================================================
 
# TESTS
 
#==============================================================================
 
@test_wrapp
 
def test_clone_with_credentials(no_errors=False):
 
    cwd = path = jn(TESTS_TMP_PATH, HG_REPO)
 

	
 
    try:
 
        shutil.rmtree(path, ignore_errors=True)
 
        os.makedirs(path)
 
@@ -369,44 +360,42 @@ def test_push_wrong_path():
 
                  {'user':USER,
 
                   'pass':PASS,
 
                   'host':HOST,
 
                   'cloned_repo':HG_REPO + '_error',
 
                   'dest':jn(TESTS_TMP_PATH, HG_REPO)}
 

	
 
    stdout, stderr = Command(cwd).execute('hg push %s' % clone_url)
 
    if not """abort: HTTP Error 403: Forbidden"""  in stderr:
 
        raise Exception('Failure')
 

	
 
@test_wrapp
 
def get_logs():
 
    sa = get_session()
 
    return len(sa.query(UserLog).all())
 
    return UserLog.query().all()
 

	
 
@test_wrapp
 
def test_logs(initial):
 
    sa = get_session()
 
    logs = sa.query(UserLog).all()
 
    operations = 7
 
    if initial + operations != len(logs):
 
        raise Exception("missing number of logs %s vs %s" % (initial, len(logs)))
 
    logs = UserLog.query().all()
 
    operations = 4
 
    if len(initial) + operations != len(logs):
 
        raise Exception("missing number of logs initial:%s vs current:%s" % \
 
                            (len(initial), len(logs)))
 

	
 

	
 
if __name__ == '__main__':
 
    create_test_user(force=False)
 
    create_test_repo()
 

	
 
    initial_logs = get_logs()
 
    print 'initial activity logs: %s' % len(initial_logs)
 

	
 
#    test_push_modify_file()
 
    test_clone_with_credentials()
 
    test_clone_wrong_credentials()
 

	
 

	
 
    test_push_new_file(commits=2, with_clone=True)
 

	
 
    test_clone_anonymous()
 
    test_push_wrong_path()
 

	
 

	
 
    test_push_wrong_credentials()
 

	
 
    test_logs(initial_logs)
0 comments (0 inline, 0 general)