"""
Routes configuration
The more specific and detailed routes should be defined first so they
may take precedent over the more generic routes. For more information
refer to the routes manual at http://routes.groovie.org/docs/
from __future__ import with_statement
from routes import Mapper
from rhodecode.lib.utils import check_repo_fast as cr
def make_map(config):
"""Create, configure and return the routes Mapper"""
rmap = Mapper(directory=config['pylons.paths']['controllers'],
always_scan=config['debug'])
rmap.minimization = False
rmap.explicit = False
def check_repo(environ, match_dict):
check for valid repository for proper 404 handling
:param environ:
:param match_dict:
repo_name = match_dict.get('repo_name')
return not cr(repo_name, config['base_path'])
# The ErrorController route (handles 404/500 error pages); it should
# likely stay at the top, ensuring it can always be resolved
rmap.connect('/error/{action}', controller='error')
rmap.connect('/error/{action}/{id}', controller='error')
#==========================================================================
# CUSTOM ROUTES HERE
#MAIN PAGE
rmap.connect('home', '/', controller='home', action='index')
rmap.connect('repo_switcher', '/repos', controller='home',
action='repo_switcher')
rmap.connect('bugtracker',
"http://bitbucket.org/marcinkuzminski/rhodecode/issues",
_static=True)
rmap.connect('rhodecode_official', "http://rhodecode.org", _static=True)
#ADMIN REPOSITORY REST ROUTES
with rmap.submapper(path_prefix='/_admin', controller='admin/repos') as m:
m.connect("repos", "/repos",
action="create", conditions=dict(method=["POST"]))
action="index", conditions=dict(method=["GET"]))
m.connect("formatted_repos", "/repos.{format}",
action="index",
conditions=dict(method=["GET"]))
m.connect("new_repo", "/repos/new",
action="new", conditions=dict(method=["GET"]))
m.connect("formatted_new_repo", "/repos/new.{format}",
m.connect("/repos/{repo_name:.*}",
action="update", conditions=dict(method=["PUT"],
function=check_repo))
action="delete", conditions=dict(method=["DELETE"],
m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
action="edit", conditions=dict(method=["GET"],
m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
m.connect("repo", "/repos/{repo_name:.*}",
action="show", conditions=dict(method=["GET"],
m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
#ajax delete repo perm user
m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
action="delete_perm_user", conditions=dict(method=["DELETE"],
#ajax delete repo perm users_group
m.connect('delete_repo_users_group',
"/repos_delete_users_group/{repo_name:.*}",
action="delete_perm_users_group",
conditions=dict(method=["DELETE"], function=check_repo))
#settings actions
m.connect('repo_stats', "/repos_stats/{repo_name:.*}",
action="repo_stats", conditions=dict(method=["DELETE"],
m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
action="repo_cache", conditions=dict(method=["DELETE"],
m.connect('repo_public_journal',
"/repos_public_journal/{repo_name:.*}",
action="repo_public_journal", conditions=dict(method=["PUT"],
m.connect('repo_pull', "/repo_pull/{repo_name:.*}",
action="repo_pull", conditions=dict(method=["PUT"],
#ADMIN REPOS GROUP REST ROUTES
rmap.resource('repos_group', 'repos_groups',
controller='admin/repos_groups', path_prefix='/_admin')
#ADMIN USER REST ROUTES
with rmap.submapper(path_prefix='/_admin', controller='admin/users') as m:
m.connect("users", "/users",
m.connect("formatted_users", "/users.{format}",
m.connect("new_user", "/users/new",
m.connect("formatted_new_user", "/users/new.{format}",
m.connect("update_user", "/users/{id}",
action="update", conditions=dict(method=["PUT"]))
m.connect("delete_user", "/users/{id}",
action="delete", conditions=dict(method=["DELETE"]))
m.connect("edit_user", "/users/{id}/edit",
action="edit", conditions=dict(method=["GET"]))
m.connect("formatted_edit_user",
"/users/{id}.{format}/edit",
m.connect("user", "/users/{id}",
action="show", conditions=dict(method=["GET"]))
m.connect("formatted_user", "/users/{id}.{format}",
#EXTRAS USER ROUTES
m.connect("user_perm", "/users_perm/{id}",
action="update_perm", conditions=dict(method=["PUT"]))
#ADMIN USERS REST ROUTES
with rmap.submapper(path_prefix='/_admin',
controller='admin/users_groups') as m:
m.connect("users_groups", "/users_groups",
m.connect("formatted_users_groups", "/users_groups.{format}",
m.connect("new_users_group", "/users_groups/new",
m.connect("formatted_new_users_group", "/users_groups/new.{format}",
m.connect("update_users_group", "/users_groups/{id}",
m.connect("delete_users_group", "/users_groups/{id}",
m.connect("edit_users_group", "/users_groups/{id}/edit",
m.connect("formatted_edit_users_group",
"/users_groups/{id}.{format}/edit",
m.connect("users_group", "/users_groups/{id}",
m.connect("formatted_users_group", "/users_groups/{id}.{format}",
m.connect("users_group_perm", "/users_groups_perm/{id}",
#ADMIN GROUP REST ROUTES
rmap.resource('group', 'groups',
controller='admin/groups', path_prefix='/_admin')
#ADMIN PERMISSIONS REST ROUTES
rmap.resource('permission', 'permissions',
controller='admin/permissions', path_prefix='/_admin')
##ADMIN LDAP SETTINGS
rmap.connect('ldap_settings', '/_admin/ldap',
controller='admin/ldap_settings', action='ldap_settings',
conditions=dict(method=["POST"]))
rmap.connect('ldap_home', '/_admin/ldap',
controller='admin/ldap_settings')
#ADMIN SETTINGS REST ROUTES
controller='admin/settings') as m:
m.connect("admin_settings", "/settings",
m.connect("formatted_admin_settings", "/settings.{format}",
m.connect("admin_new_setting", "/settings/new",
m.connect("formatted_admin_new_setting", "/settings/new.{format}",
m.connect("/settings/{setting_id}",
m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
m.connect("formatted_admin_edit_setting",
"/settings/{setting_id}.{format}/edit",
m.connect("admin_setting", "/settings/{setting_id}",
m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
m.connect("admin_settings_my_account", "/my_account",
action="my_account", conditions=dict(method=["GET"]))
m.connect("admin_settings_my_account_update", "/my_account_update",
action="my_account_update", conditions=dict(method=["PUT"]))
m.connect("admin_settings_create_repository", "/create_repository",
action="create_repository", conditions=dict(method=["GET"]))
#ADMIN MAIN PAGES
with rmap.submapper(path_prefix='/_admin', controller='admin/admin') as m:
m.connect('admin_home', '', action='index')
m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
action='add_repo')
#USER JOURNAL
rmap.connect('journal', '/_admin/journal', controller='journal')
rmap.connect('public_journal', '/_admin/public_journal',
controller='journal', action="public_journal")
rmap.connect('public_journal_rss', '/_admin/public_journal_rss',
controller='journal', action="public_journal_rss")
rmap.connect('public_journal_atom', '/_admin/public_journal_atom',
controller='journal', action="public_journal_atom")
rmap.connect('toggle_following', '/_admin/toggle_following',
controller='journal', action='toggle_following',
#SEARCH
rmap.connect('search', '/_admin/search', controller='search',)
rmap.connect('search_repo', '/_admin/search/{search_repo:.*}',
controller='search')
#LOGIN/LOGOUT/REGISTER/SIGN IN
rmap.connect('login_home', '/_admin/login', controller='login')
rmap.connect('logout_home', '/_admin/logout', controller='login',
action='logout')
rmap.connect('register', '/_admin/register', controller='login',
action='register')
rmap.connect('reset_password', '/_admin/password_reset',
controller='login', action='password_reset')
#FEEDS
rmap.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
controller='feed', action='rss',
conditions=dict(function=check_repo))
rmap.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
controller='feed', action='atom',
# REPOSITORY ROUTES
rmap.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
controller='changeset', revision='tip',
rmap.connect('raw_changeset_home',
'/{repo_name:.*}/raw-changeset/{revision}',
controller='changeset', action='raw_changeset',
revision='tip', conditions=dict(function=check_repo))
rmap.connect('summary_home', '/{repo_name:.*}',
controller='summary', conditions=dict(function=check_repo))
rmap.connect('summary_home', '/{repo_name:.*}/summary',
rmap.connect('shortlog_home', '/{repo_name:.*}/shortlog',
controller='shortlog', conditions=dict(function=check_repo))
rmap.connect('branches_home', '/{repo_name:.*}/branches',
controller='branches', conditions=dict(function=check_repo))
rmap.connect('tags_home', '/{repo_name:.*}/tags',
controller='tags', conditions=dict(function=check_repo))
rmap.connect('changelog_home', '/{repo_name:.*}/changelog',
controller='changelog', conditions=dict(function=check_repo))
rmap.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
controller='files', revision='tip', f_path='',
rmap.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
controller='files', action='diff', revision='tip', f_path='',
rmap.connect('files_rawfile_home',
'/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
controller='files', action='rawfile', revision='tip',
f_path='', conditions=dict(function=check_repo))
rmap.connect('files_raw_home',
'/{repo_name:.*}/raw/{revision}/{f_path:.*}',
controller='files', action='raw', revision='tip', f_path='',
rmap.connect('files_annotate_home',
'/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
controller='files', action='annotate', revision='tip',
rmap.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}',
controller='files', action='archivefile',
rmap.connect('repo_settings_delete', '/{repo_name:.*}/settings',
controller='settings', action="delete",
rmap.connect('repo_settings_update', '/{repo_name:.*}/settings',
controller='settings', action="update",
conditions=dict(method=["PUT"], function=check_repo))
rmap.connect('repo_settings_home', '/{repo_name:.*}/settings',
controller='settings', action='index',
rmap.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
controller='settings', action='fork_create',
conditions=dict(function=check_repo, method=["POST"]))
rmap.connect('repo_fork_home', '/{repo_name:.*}/fork',
controller='settings', action='fork',
rmap.connect('repo_followers_home', '/{repo_name:.*}/followers',
controller='followers', action='followers',
rmap.connect('repo_forks_home', '/{repo_name:.*}/forks',
controller='forks', action='forks',
return rmap
# -*- coding: utf-8 -*-
rhodecode.controllers.followers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Followers controller for rhodecode
:created_on: Apr 23, 2011
:author: marcink
:copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
: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 pylons import tmpl_context as c, request
from rhodecode.lib.helpers import Page
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
from rhodecode.lib.base import BaseRepoController, render
from rhodecode.model.db import Repository, User, UserFollowing
log = logging.getLogger(__name__)
class FollowersController(BaseRepoController):
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
def __before__(self):
super(FollowersController, self).__before__()
def followers(self, repo_name):
p = int(request.params.get('page', 1))
repo_id = getattr(Repository.by_repo_name(repo_name), 'repo_id')
repo_id = Repository.by_repo_name(repo_name).repo_id
d = UserFollowing.get_repo_followers(repo_id)\
.order_by(UserFollowing.follows_from)
c.followers_pager = Page(d, page=p, items_per_page=20)
c.followers_data = render('/followers/followers_data.html')
if request.params.get('partial'):
return c.followers_data
return render('/followers/followers.html')
new file 100644
rhodecode.controllers.forks
forks controller for rhodecode
class ForksController(BaseRepoController):
super(ForksController, self).__before__()
def forks(self, repo_name):
d = Repository.get_repo_forks(repo_id)
c.forks_pager = Page(d, page=p, items_per_page=20)
c.forks_data = render('/forks/forks_data.html')
return c.forks_data
return render('/forks/forks.html')
rhodecode.model.db
~~~~~~~~~~~~~~~~~~
Database Models for RhodeCode
:created_on: Apr 08, 2010
import os
import datetime
from datetime import date
from sqlalchemy import *
from sqlalchemy.exc import DatabaseError
from sqlalchemy.orm import relationship, backref
from sqlalchemy.orm.interfaces import MapperExtension
from rhodecode.lib import str2bool
from rhodecode.model.meta import Base, Session
from rhodecode.model.caching_query import FromCache
#==============================================================================
# MAPPER EXTENSIONS
class RepositoryMapper(MapperExtension):
def after_update(self, mapper, connection, instance):
pass
class RhodeCodeSettings(Base):
__tablename__ = 'rhodecode_settings'
__table_args__ = (UniqueConstraint('app_settings_name'), {'useexisting':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=''):
self.app_settings_name = k
self.app_settings_value = v
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)\
.filter(cls.app_settings_name == ldap_key).scalar()
def get_app_settings(cls, cache=False):
ret = Session.query(cls)
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
def get_ldap_settings(cls, cache=False):
ret = Session.query(cls)\
.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):
__tablename__ = 'rhodecode_ui'
__table_args__ = {'useexisting':True}
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)
class User(Base):
__tablename__ = 'users'
__table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
active = Column("active", Boolean(), nullable=True, unique=None, default=None)
admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
name = Column("name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
user_log = relationship('UserLog', cascade='all')
user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
repositories = relationship('Repository')
user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
group_member = relationship('UsersGroupMember', cascade='all')
@property
def full_contact(self):
return '%s %s <%s>' % (self.name, self.lastname, self.email)
def short_contact(self):
return '%s %s' % (self.name, self.lastname)
def is_admin(self):
return self.admin
return "<%s('id:%s:%s')>" % (self.__class__.__name__,
self.user_id, self.username)
def by_username(cls, username):
return Session.query(cls).filter(cls.username == username).one()
def update_lastlogin(self):
"""Update user lastlogin"""
try:
session = Session.object_session(self)
self.last_login = datetime.datetime.now()
session.add(self)
session.commit()
log.debug('updated user %s lastlogin', self.username)
except (DatabaseError,):
session.rollback()
class UserLog(Base):
__tablename__ = 'user_logs'
user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
repository_id = Column("repository_id", Integer(length=None, convert_unicode=False, assert_unicode=None), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
action = Column("action", UnicodeText(length=1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
def action_as_day(self):
return date(*self.action_date.timetuple()[:3])
user = relationship('User')
repository = relationship('Repository')
class UsersGroup(Base):
__tablename__ = 'users_groups'
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 get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
if case_insensitive:
gr = Session.query(cls)\
.filter(cls.users_group_name.ilike(group_name))
else:
gr = Session.query(UsersGroup)\
.filter(UsersGroup.users_group_name == group_name)
gr = gr.options(FromCache("sql_cache_short",
"get_user_%s" % group_name))
return gr.scalar()
class UsersGroupMember(Base):
__tablename__ = 'users_groups_members'
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 = 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
class Repository(Base):
__tablename__ = 'repositories'
__table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
__mapper_args__ = {'extension':RepositoryMapper()}
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)
description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
fork = relationship('Repository', remote_side=repo_id)
group = relationship('Group')
repo_to_perm = relationship('RepoToPerm', cascade='all', order_by='RepoToPerm.repo_to_perm_id')
users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
stats = relationship('Statistics', cascade='all', uselist=False)
followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
logs = relationship('UserLog', cascade='all')
self.repo_id, self.repo_name)
def by_repo_name(cls, repo_name):
return Session.query(cls).filter(cls.repo_name == repo_name).one()
def get_repo_forks(cls, repo_id):
return Session.query(cls).filter(Repository.fork_id == repo_id)
def just_name(self):
return self.repo_name.split(os.sep)[-1]
def groups_with_parents(self):
groups = []
if self.group is None:
return groups
cur_gr = self.group
groups.insert(0, cur_gr)
while 1:
gr = getattr(cur_gr, 'parent_group', None)
cur_gr = cur_gr.parent_group
if gr is None:
break
groups.insert(0, gr)
def groups_and_repo(self):
return self.groups_with_parents, self.just_name
class Group(Base):
__tablename__ = 'groups'
__table_args__ = (UniqueConstraint('group_name'), {'useexisting':True},)
group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
parent_group = relationship('Group', remote_side=group_id)
def __init__(self, group_name='', parent_group=None):
self.group_name = group_name
self.parent_group = parent_group
return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
self.group_name)
def parents(self):
if self.parent_group is None:
cur_gr = self.parent_group
def repositories(self):
return Session.query(Repository).filter(Repository.group == self).all()
class Permission(Base):
__tablename__ = 'permissions'
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)
self.permission_id, self.permission_name)
def get_by_key(cls, key):
return Session.query(cls).filter(cls.permission_name == key).scalar()
class RepoToPerm(Base):
__tablename__ = 'repo_to_perm'
__table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
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)
permission = relationship('Permission')
class UserToPerm(Base):
__tablename__ = 'user_to_perm'
__table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
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)\
.filter(cls.permission == perm).scalar() is not None
def grant_perm(cls, user_id, perm):
new = cls()
new.user_id = user_id
new.permission = perm
Session.add(new)
Session.commit()
except:
Session.rollback()
def revoke_perm(cls, user_id, perm):
Session.query(cls).filter(cls.user_id == user_id)\
.filter(cls.permission == perm).delete()
class UsersGroupRepoToPerm(Base):
__tablename__ = 'users_group_repo_to_perm'
__table_args__ = (UniqueConstraint('users_group_id', 'permission_id'), {'useexisting':True})
users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
class UsersGroupToPerm(Base):
__tablename__ = 'users_group_to_perm'
def has_perm(cls, users_group_id, perm):
return Session.query(cls).filter(cls.users_group_id ==
users_group_id)\
.filter(cls.permission == perm)\
.scalar() is not None
def grant_perm(cls, users_group_id, perm):
new.users_group_id = users_group_id
def revoke_perm(cls, users_group_id, perm):
Session.query(cls).filter(cls.users_group_id == users_group_id)\
class GroupToPerm(Base):
__tablename__ = 'group_to_perm'
__table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'useexisting':True})
group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
class Statistics(Base):
__tablename__ = 'statistics'
__table_args__ = (UniqueConstraint('repository_id'), {'useexisting':True})
stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
repository = relationship('Repository', single_parent=True)
class UserFollowing(Base):
__tablename__ = 'user_followings'
__table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
UniqueConstraint('user_id', 'follows_user_id')
, {'useexisting':True})
user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
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')
def get_repo_followers(cls, repo_id):
return Session.query(cls).filter(cls.follows_repo_id == repo_id)
class CacheInvalidation(Base):
__tablename__ = 'cache_invalidation'
__table_args__ = (UniqueConstraint('cache_key'), {'useexisting':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
self.cache_args = cache_args
self.cache_active = False
self.cache_id, self.cache_key)
class DbMigrateVersion(Base):
__tablename__ = 'db_migrate_version'
repository_id = Column('repository_id', String(250), primary_key=True)
repository_path = Column('repository_path', Text)
version = Column('version', Integer)
## -*- coding: utf-8 -*-
<%inherit file="root.html"/>
<!-- HEADER -->
<div id="header">
<!-- user -->
<ul id="logged-user">
<li class="first">
<div class="gravatar">
<img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,20)}" />
</div>
<div class="account">
%if c.rhodecode_user.username == 'default':
<a href="${h.url('public_journal')}">${_('Public journal')}</a>
%else:
${h.link_to(c.rhodecode_user.username,h.url('admin_settings_my_account'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
%endif
</li>
<li>
<a href="${h.url('home')}">${_('Home')}</a>
%if c.rhodecode_user.username != 'default':
<a href="${h.url('journal')}">${_('Journal')}</a>
##(${c.unread_journal}
<li class="last highlight">${h.link_to(u'Login',h.url('login_home'))}</li>
<li class="last highlight">${h.link_to(u'Log Out',h.url('logout_home'))}</li>
</ul>
<!-- end user -->
<div id="header-inner" class="title top-left-rounded-corner top-right-rounded-corner">
<div id="logo">
<h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
<!-- MENU -->
${self.page_nav()}
<!-- END MENU -->
${self.body()}
<!-- END HEADER -->
<!-- CONTENT -->
<div id="content">
<div class="flash_msg">
<% messages = h.flash.pop_messages() %>
% if messages:
<ul id="flash-messages">
% for message in messages:
<li class="${message.category}_msg">${message}</li>
% endfor
% endif
<div id="main">
${next.main()}
<!-- END CONTENT -->
<!-- FOOTER -->
<div id="footer">
<div id="footer-inner" class="title bottom-left-rounded-corner bottom-right-rounded-corner">
<div>
<p class="footer-link">
<a href="${h.url('bugtracker')}">${_('Submit a bug')}</a>
</p>
<p class="footer-link-right">
<a href="${h.url('rhodecode_official')}">RhodeCode</a>
${c.rhodecode_version} © 2010-${h.datetime.today().year} by Marcin Kuzminski
<script type="text/javascript">
function tooltip_activate(){
${h.tooltip.activate()}
}
tooltip_activate();
</script>
<!-- END FOOTER -->
### MAKO DEFS ###
<%def name="page_nav()">
${self.menu()}
</%def>
<%def name="breadcrumbs()">
<div class="breadcrumbs">
${self.breadcrumbs_links()}
<%def name="menu(current=None)">
<%
def is_current(selected):
if selected == current:
return h.literal('class="current"')
%>
%if current not in ['home','admin']:
##REGULAR MENU
<ul id="quick">
<!-- repo switcher -->
<a id="repo_switcher" title="${_('Switch repository')}" href="#">
<span class="icon">
<img src="${h.url("/images/icons/database.png")}" alt="${_('Products')}" />
</span>
<span>↓</span>
</a>
<ul id="repo_switcher_list" class="repo_switcher">
<a href="#">${_('loading...')}</a>
YUE.on('repo_switcher','mouseover',function(){
function qfilter(){
var S = YAHOO.util.Selector;
var q_filter = YUD.get('q_filter_rs');
var F = YAHOO.namespace('q_filter_rs');
YUE.on(q_filter,'click',function(){
q_filter.value = '';
});
F.filterTimeout = null;
F.updateFilter = function() {
// Reset timeout
var obsolete = [];
var nodes = S.query('ul#repo_switcher_list li a.repo_name');
var req = YUD.get('q_filter_rs').value;
for (n in nodes){
YUD.setStyle(nodes[n].parentNode,'display','')
if (req){
console.log(n);
if (nodes[n].innerHTML.toLowerCase().indexOf(req) == -1) {
obsolete.push(nodes[n]);
if(obsolete){
for (n in obsolete){
YUD.setStyle(obsolete[n].parentNode,'display','none');
YUE.on(q_filter,'keyup',function(e){
clearTimeout(F.filterTimeout);
setTimeout(F.updateFilter,600);
var loaded = YUD.hasClass('repo_switcher','loaded');
if(!loaded){
YUD.addClass('repo_switcher','loaded');
YAHOO.util.Connect.asyncRequest('GET',"${h.url('repo_switcher')}",{
success:function(o){
YUD.get('repo_switcher_list').innerHTML = o.responseText;
qfilter();
},
failure:function(o){
YUD.removeClass('repo_switcher','loaded');
},null);
return false;
<li ${is_current('summary')}>
<a title="${_('Summary')}" href="${h.url('summary_home',repo_name=c.repo_name)}">
<img src="${h.url("/images/icons/clipboard_16.png")}" alt="${_('Summary')}" />
<span>${_('Summary')}</span>
##<li ${is_current('shortlog')}>
## <a title="${_('Shortlog')}" href="${h.url('shortlog_home',repo_name=c.repo_name)}">
## <span class="icon">
## <img src="${h.url("/images/icons/application_view_list.png")}" alt="${_('Shortlog')}" />
## </span>
## <span>${_('Shortlog')}</span>
## </a>
##</li>
<li ${is_current('changelog')}>
<a title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=c.repo_name)}">
<img src="${h.url("/images/icons/time.png")}" alt="${_('Changelog')}" />
<span>${_('Changelog')}</span>
<li ${is_current('switch_to')}>
<a title="${_('Switch to')}" href="#">
<img src="${h.url("/images/icons/arrow_switch.png")}" alt="${_('Switch to')}" />
<span>${_('Switch to')}</span>
<ul>
${h.link_to('%s (%s)' % (_('branches'),len(c.rhodecode_repo.branches.values()),),h.url('branches_home',repo_name=c.repo_name),class_='branches childs')}
%if c.rhodecode_repo.branches.values():
%for cnt,branch in enumerate(c.rhodecode_repo.branches.items()):
<li>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=branch[1]))}</li>
%endfor
<li>${h.link_to(_('There are no branches yet'),'#')}</li>
${h.link_to('%s (%s)' % (_('tags'),len(c.rhodecode_repo.tags.values()),),h.url('tags_home',repo_name=c.repo_name),class_='tags childs')}
%if c.rhodecode_repo.tags.values():
%for cnt,tag in enumerate(c.rhodecode_repo.tags.items()):
<li>${h.link_to('%s - %s' % (tag[0],h.short_id(tag[1])),h.url('files_home',repo_name=c.repo_name,revision=tag[1]))}</li>
<li>${h.link_to(_('There are no tags yet'),'#')}</li>
<li ${is_current('files')}>
<a title="${_('Files')}" href="${h.url('files_home',repo_name=c.repo_name)}">
<img src="${h.url("/images/icons/file.png")}" alt="${_('Files')}" />
<span>${_('Files')}</span>
<li ${is_current('options')}>
<a title="${_('Options')}" href="#">
<img src="${h.url("/images/icons/table_gear.png")}" alt="${_('Admin')}" />
<span>${_('Options')}</span>
%if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
%if h.HasPermissionAll('hg.admin')('access settings on repository'):
<li>${h.link_to(_('settings'),h.url('edit_repo',repo_name=c.repo_name),class_='settings')}</li>
<li>${h.link_to(_('settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}</li>
<li>${h.link_to(_('fork'),h.url('repo_fork_home',repo_name=c.repo_name),class_='fork')}</li>
<li>${h.link_to(_('search'),h.url('search_repo',search_repo=c.repo_name),class_='search')}</li>
%if h.HasPermissionAll('hg.admin')('access admin main page'):
${h.link_to(_('admin'),h.url('admin_home'),class_='admin')}
<%def name="admin_menu()">
<li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
<li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
<li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
<li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li>
<li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
<li>${h.link_to(_('ldap'),h.url('ldap_home'),class_='ldap')}</li>
<li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
${admin_menu()}
<a title="${_('Followers')}" href="${h.url('repo_followers_home',repo_name=c.repo_name)}">
<span class="icon_short">
<img src="${h.url("/images/icons/heart.png")}" alt="${_('Followers')}" />
<span id="current_followers_count" class="short">${c.repository_followers}</span>
<a title="${_('Forks')}" href="#">
<a title="${_('Forks')}" href="${h.url('repo_forks_home',repo_name=c.repo_name)}">
<img src="${h.url("/images/icons/arrow_divide.png")}" alt="${_('Forks')}" />
<span class="short">${c.repository_forks}</span>
##ROOT MENU
<a title="${_('Home')}" href="${h.url('home')}">
<img src="${h.url("/images/icons/home_16.png")}" alt="${_('Home')}" />
<span>${_('Home')}</span>
<a title="${_('Journal')}" href="${h.url('journal')}">
<img src="${h.url("/images/icons/book.png")}" alt="${_('Journal')}" />
<span>${_('Journal')}</span>
<a title="${_('Search')}" href="${h.url('search')}">
<img src="${h.url("/images/icons/search_16.png")}" alt="${_('Search')}" />
<span>${_('Search')}</span>
<li ${is_current('admin')}>
<a title="${_('Admin')}" href="${h.url('admin_home')}">
<img src="${h.url("/images/icons/cog_edit.png")}" alt="${_('Admin')}" />
<span>${_('Admin')}</span>
\ No newline at end of file
<%inherit file="/base/base.html"/>
<%def name="title()">
${c.repo_name} ${_('Forks')} - ${c.rhodecode_name}
<%def name="breadcrumbs_links()">
${h.link_to(u'Home',h.url('/'))}
»
${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
${_('forks')}
${self.menu('forks')}
<%def name="main()">
<div class="box">
<!-- box / title -->
<div class="title">
${self.breadcrumbs()}
<!-- end box / title -->
<div class="table">
<div id="forks">
${c.forks_data}
% for f in c.forks_pager:
<div class="fork_user">
<img alt="gravatar" src="${h.gravatar_url(f.user.email,24)}"/>
<span style="font-size: 20px">
<b>${f.user.username}</b> (${f.user.name} ${f.user.lastname}) /
${h.link_to(f.repo_name,h.url('summary_home',repo_name=f.repo_name))}
<div style="padding:5px 3px 3px 42px;">${f.description}</div>
<div style="clear:both;padding-top: 10px"></div>
<div class="follower_date">${_('forked')} -
<span class="tooltip" title="${f.created_on}"> ${h.age(f.created_on)}</span></div>
<div style="border-bottom: 1px solid #DDD;margin:10px 0px 10px 0px"></div>
<div class="pagination-wh pagination-left">
var data_div = 'forks';
YAHOO.util.Event.onDOMReady(function(){
YAHOO.util.Event.addListener(
YUD.getElementsByClassName('pager_link'),"click",
function(){
YAHOO.util.Dom.setStyle(data_div,'opacity','0.3');
${c.forks_pager.pager('$link_previous ~2~ $link_next',
onclick="""YAHOO.util.Connect.asyncRequest('GET','$partial_url',{
success:function(o){YAHOO.util.Dom.get(data_div).innerHTML=o.responseText;
YUE.on(YAHOO.util.Dom.getElementsByClassName('pager_link'),"click",function(){
YAHOO.util.Dom.setStyle(data_div,'opacity','0.3');});
YAHOO.util.Dom.setStyle(data_div,'opacity','1');}},null); return false;""")}
Status change: