# -*- coding: utf-8 -*-
"""
rhodecode.controllers.settings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Settings controller for rhodecode
:created_on: Jun 30, 2010
: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; version 2
# of the License or (at your opinion) any later version of the license.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
import logging
import traceback
import formencode
from pylons import tmpl_context as c, request, url
from pylons.controllers.util import redirect
from pylons.i18n.translation import _
import rhodecode.lib.helpers as h
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAllDecorator
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
log = logging.getLogger(__name__)
class SettingsController(BaseRepoController):
@LoginRequired()
@HasRepoPermissionAllDecorator('repository.admin')
def __before__(self):
super(SettingsController, self).__before__()
def index(self, repo_name):
repo_model = RepoModel()
c.repo_info = repo = repo_model.get_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()
#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:
return formencode.htmlfill.render(
render('settings/repo_settings.html'),
defaults=defaults,
encoding="UTF-8",
force_defaults=False
)
def update(self, repo_name):
changed_name = repo_name
_form = RepoSettingsForm(edit=True, old_data={'repo_name':repo_name})()
try:
form_result = _form.to_python(dict(request.POST))
repo_model.update(repo_name, form_result)
invalidate_cache('get_repo_cached_%s' % repo_name)
h.flash(_('Repository %s updated successfully' % repo_name),
category='success')
changed_name = form_result['repo_name']
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)
errors.value.update({'user':c.repo_info.user.username})
defaults=errors.value,
errors=errors.error_dict or {},
prefix_error=False,
encoding="UTF-8")
except Exception:
log.error(traceback.format_exc())
h.flash(_('error occurred during update of repository %s') \
% repo_name, category='error')
return redirect(url('repo_settings_home', repo_name=changed_name))
def delete(self, repo_name):
"""DELETE /repos/repo_name: Delete an existing item"""
# Forms posted to this method should contain a hidden field:
# <input type="hidden" name="_method" value="DELETE" />
# Or using helpers:
# h.form(url('repo_settings_delete', repo_name=ID),
# method='delete')
# url('repo_settings_delete', repo_name=ID)
repo = repo_model.get_by_repo_name(repo_name)
' it was moved or renamed from the filesystem'
action_logger(self.rhodecode_user, 'user_deleted_repo',
repo_name, '', self.sa)
repo_model.delete(repo)
h.flash(_('deleted repository %s') % repo_name, category='success')
h.flash(_('An error occurred during deletion of %s') % repo_name,
@HasRepoPermissionAllDecorator('repository.read')
def fork(self, repo_name):
return render('settings/repo_fork.html')
def fork_create(self, repo_name):
_form = RepoForkForm(old_data={'repo_type':c.repo_info.repo_type})()
form_result = {}
form_result.update({'repo_name':repo_name})
repo_model.create_fork(form_result, c.rhodecode_user)
h.flash(_('forked %s repository as %s') \
% (repo_name, form_result['fork_name']),
action_logger(self.rhodecode_user,
'user_forked_repo:%s' % form_result['fork_name'],
c.new_repo = errors.value['fork_name']
r = render('settings/repo_fork.html')
r,
@@ -44,349 +44,349 @@
${h.link_to('anonymous',h.url('#'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
%endif
%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))}
</div>
</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})</a>
%if c.rhodecode_user.username == 'default':
<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">
<!-- logo -->
<div id="logo">
<h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
<!-- end logo -->
<!-- menu -->
${self.page_nav()}
<!-- quick -->
<!-- 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">${h.link_to(_('Submit a bug'),h.url('bugtracker'))}</p>
<p class="footer-link">${h.link_to(_('GPL license'),h.url('gpl_license'))}</p>
<p>RhodeCode ${c.rhodecode_version} © 2010-2011 by Marcin Kuzminski</p>
<script type="text/javascript">
function tooltip_activate(){
${h.tooltip.activate()}
}
tooltip_activate();
</script>
<!-- end footer -->
</body>
</html>
### MAKO DEFS ###
<%def name="page_nav()">
${self.menu()}
</%def>
<%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 class="repo_switcher">
%for repo in c.cached_repo_list:
%if repo['dbrepo']['private']:
<li><img src="${h.url("/images/icons/lock.png")}" alt="${_('Private repository')}" class="repo_switcher_type"/>${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="%s" % repo['dbrepo']['repo_type'])}</li>
<li><img src="${h.url("/images/icons/lock_open.png")}" alt="${_('Public repository')}" class="repo_switcher_type" />${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="%s" % repo['dbrepo']['repo_type'])}</li>
%endfor
<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>
<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="#">
<span class="icon_short">
<img src="${h.url("/images/icons/heart.png")}" alt="${_('Followers')}" />
<span class="short">${c.repository_followers}</span>
<a title="${_('Forks')}" href="#">
<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>
<%def name="css()">
<link rel="stylesheet" type="text/css" href="${h.url('/css/style.css')}" media="screen" />
<link rel="stylesheet" type="text/css" href="${h.url('/css/pygments.css')}" />
<link rel="stylesheet" type="text/css" href="${h.url('/css/diff.css')}" />
<%def name="js()">
##<script type="text/javascript" src="${h.url('/js/yui/utilities/utilities.js')}"></script>
##<script type="text/javascript" src="${h.url('/js/yui/container/container.js')}"></script>
##<script type="text/javascript" src="${h.url('/js/yui/datasource/datasource.js')}"></script>
##<script type="text/javascript" src="${h.url('/js/yui/autocomplete/autocomplete.js')}"></script>
##<script type="text/javascript" src="${h.url('/js/yui/selector/selector-min.js')}"></script>
<script type="text/javascript" src="${h.url('/js/yui2a.js')}"></script>
<!--[if IE]><script language="javascript" type="text/javascript" src="${h.url('/js/excanvas.min.js')}"></script><![endif]-->
<script type="text/javascript" src="${h.url('/js/yui.flot.js')}"></script>
var base_url = "${h.url('toggle_following')}";
var YUC = YAHOO.util.Connect;
var YUD = YAHOO.util.Dom;
var YUE = YAHOO.util.Event;
function onSuccess(target){
var f = YUD.get(target.id);
if(f.getAttribute('class')=='follow'){
f.setAttribute('class','following');
f.setAttribute('title',"${_('Stop following this repository')}");
else{
f.setAttribute('class','follow');
f.setAttribute('title',"${_('Start following this repository')}");
function toggleFollowingUser(fallows_user_id,token){
args = 'follows_user_id='+fallows_user_id;
args+= '&auth_token='+token;
YUC.asyncRequest('POST',base_url,{
success:function(o){
onSuccess();
},args); return false;
function toggleFollowingRepo(target,fallows_repo_id,token){
args = 'follows_repo_id='+fallows_repo_id;
onSuccess(target);
<%def name="breadcrumbs()">
<div class="breadcrumbs">
${self.breadcrumbs_links()}
\ No newline at end of file
Status change: