@@ -70,12 +70,17 @@ def make_map(config):
action="show", conditions=dict(method=["GET"],
function=check_repo))
#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"],
#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"],
@@ -212,29 +212,44 @@ class ReposController(BaseController):
category='error')
return redirect(url('repos'))
@HasPermissionAllDecorator('hg.admin')
def delete_perm_user(self, repo_name):
"""
DELETE an existing repository permission user
"""DELETE an existing repository permission user
:param repo_name:
try:
repo_model = RepoModel()
repo_model.delete_perm_user(request.POST, repo_name)
except Exception, e:
h.flash(_('An error occurred during deletion of repository user'),
raise HTTPInternalServerError()
def repo_stats(self, repo_name):
def delete_perm_users_group(self, repo_name):
"""DELETE an existing repository permission users group
DELETE an existing repository statistics
repo_model.delete_perm_users_group(request.POST, repo_name)
h.flash(_('An error occurred during deletion of repository'
' users groups'),
"""DELETE an existing repository statistics
repo_model.delete_stats(repo_name)
@@ -242,14 +257,14 @@ class ReposController(BaseController):
h.flash(_('An error occurred during deletion of repository stats'),
return redirect(url('edit_repo', repo_name=repo_name))
def repo_cache(self, repo_name):
INVALIDATE existing repository cache
"""INVALIDATE existing repository cache
ScmModel().mark_for_invalidation(repo_name)
@@ -264,14 +279,15 @@ class ReposController(BaseController):
def edit(self, repo_name, format='html'):
"""GET /repos/repo_name/edit: Form to edit an existing item"""
# url('edit_repo', repo_name=ID)
c.repo_info = repo_model.get_by_repo_name(repo_name)
r = ScmModel().get(repo_name)
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,
@@ -290,25 +306,34 @@ class ReposController(BaseController):
if last_rev == 0 or c.repo_last_rev == 0:
c.stats_percentage = 0
else:
c.stats_percentage = '%.2f' % ((float((last_rev)) /
c.repo_last_rev) * 100)
c.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})
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({'perm_%s' % p.user.username:
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 htmlfill.render(
render('admin/repos/repo_edit.html'),
defaults=defaults,
encoding="UTF-8",
@@ -38,12 +38,13 @@ from pylons.i18n.translation import _
import rhodecode.lib.helpers as h
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAllDecorator
from rhodecode.lib.base import BaseController, 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(BaseController):
@LoginRequired()
@@ -59,18 +60,34 @@ class SettingsController(BaseController)
' it was created or renamed from the file system'
return redirect(url('home'))
render('settings/repo_settings.html'),
@@ -199,12 +199,13 @@ class Repository(Base, BaseModel):
group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
user = relationship('User')
fork = relationship('Repository', remote_side=repo_id)
group = relationship('Group')
repo_to_perm = relationship('RepoToPerm', cascade='all')
users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
stats = relationship('Statistics', cascade='all', uselist=False)
repo_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
logs = relationship('UserLog', cascade='all')
@@ -243,30 +243,31 @@ class ValidPerms(formencode.validators.F
def to_python(self, value, state):
perms_update = []
perms_new = []
#build a list of permission to update and new permission to create
for k, v in value.items():
if k.startswith('perm_'):
if k.startswith('perm_new_member'):
#means new added member to permissions
new_perm = value.get('perm_new_member', False)
new_member = value.get('perm_new_member_name', False)
new_type = value.get('perm_new_member_type')
if new_member and new_perm:
if (new_member, new_perm, new_type) not in perms_new:
perms_new.append((new_member, new_perm, new_type))
usr = k[5:]
t = 'user'
if usr == 'default':
if value['private']:
#set none for default when updating to private repo
v = 'repository.none'
perms_update.append((usr, v, t))
elif k.startswith('u_perm_') or k.startswith('g_perm_'):
member = k[7:]
t = {'u':'user',
'g':'users_group'}[k[0]]
if member == 'default':
perms_update.append((member, v, t))
value['perms_updates'] = perms_update
value['perms_new'] = perms_new
#update permissions
sa = meta.Session
for k, v, t in perms_new:
@@ -349,14 +350,16 @@ class LdapLibValidator(formencode.valida
class AttrLoginValidator(formencode.validators.FancyValidator):
if not value or not isinstance(value, (str, unicode)):
raise formencode.Invalid(_("The LDAP Login attribute of the CN must be specified "
"- this is the name of the attribute that is equivalent to 'username'"),
raise formencode.Invalid(_("The LDAP Login attribute of the CN "
"must be specified - this is the name "
"of the attribute that is equivalent "
"to 'username'"),
value, state)
return value
#===============================================================================
# FORMS
@@ -252,12 +252,25 @@ class RepoModel(BaseModel):
self.sa.commit()
except:
log.error(traceback.format_exc())
self.sa.rollback()
raise
def delete_perm_users_group(self, form_data, repo_name):
self.sa.query(UsersGroupToPerm)\
.filter(UsersGroupToPerm.repository \
== self.get_by_repo_name(repo_name))\
.filter(UsersGroupToPerm.users_group_id \
== form_data['users_group_id']).delete()
def delete_stats(self, repo_name):
self.sa.query(Statistics)\
.filter(Statistics.repository == \
self.get_by_repo_name(repo_name)).delete()
@@ -90,82 +90,14 @@
<div class="field">
<div class="label">
<label for="input">${_('Permissions')}:</label>
</div>
<div class="input">
<table id="permissions_manage">
<tr>
<td>${_('none')}</td>
<td>${_('read')}</td>
<td>${_('write')}</td>
<td>${_('admin')}</td>
<td>${_('member')}</td>
<td></td>
</tr>
%for r2p in c.repo_info.repo_to_perm:
%if r2p.user.username =='default' and c.repo_info.private:
<td colspan="4">
<span class="private_repo_msg">
${_('private repository')}
</span>
</td>
<td class="private_repo_msg">${r2p.user.username}</td>
%else:
<tr id="id${id(r2p.user.username)}">
<td>${h.radio('perm_%s' % r2p.user.username,'repository.none')}</td>
<td>${h.radio('perm_%s' % r2p.user.username,'repository.read')}</td>
<td>${h.radio('perm_%s' % r2p.user.username,'repository.write')}</td>
<td>${h.radio('perm_%s' % r2p.user.username,'repository.admin')}</td>
<td>${r2p.user.username}</td>
<td>
%if r2p.user.username !='default':
<span class="delete_icon action_button" onclick="ajaxAction(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
<script type="text/javascript">
function ajaxAction(user_id,field_id){
var sUrl = "${h.url('delete_repo_user',repo_name=c.repo_name)}";
var callback = { success:function(o){
var tr = YAHOO.util.Dom.get(String(field_id));
tr.parentNode.removeChild(tr);},failure:function(o){
alert("${_('Failed to remove user')}");},};
var postData = '_method=delete&user_id='+user_id;
var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);};
</script>
%endif
%endfor
<tr id="add_perm_input">
<td>${h.radio('perm_new_member','repository.none')}</td>
<td>${h.radio('perm_new_member','repository.read')}</td>
<td>${h.radio('perm_new_member','repository.write')}</td>
<td>${h.radio('perm_new_member','repository.admin')}</td>
<td class='ac'>
<div class="perm_ac" id="perm_ac">
${h.text('perm_new_member_name',class_='yui-ac-input')}
${h.hidden('perm_new_member_type')}
<div id="perm_container"></div>
<td colspan="6">
<span id="add_perm" class="add_icon" style="cursor: pointer;">
${_('Add another member')}
</table>
<%include file="repo_edit_perms.html"/>
<div class="buttons">
${h.submit('save','Save',class_="ui-button")}
${h.reset('reset','Reset',class_="ui-button")}
new file 100644
## USERS
function ajaxActionUser(user_id,field_id){
var tr = YUD.get(String(field_id));
tr.parentNode.removeChild(tr);},
failure:function(o){
<td class="private_repo_msg"><img style="vertical-align:bottom" src="/images/icons/user.png"/>${r2p.user.username}</td>
<td>${h.radio('u_perm_%s' % r2p.user.username,'repository.none')}</td>
<td>${h.radio('u_perm_%s' % r2p.user.username,'repository.read')}</td>
<td>${h.radio('u_perm_%s' % r2p.user.username,'repository.write')}</td>
<td>${h.radio('u_perm_%s' % r2p.user.username,'repository.admin')}</td>
<td style="white-space: nowrap;"><img style="vertical-align:bottom" src="/images/icons/user.png"/>${r2p.user.username}</td>
<span class="delete_icon action_button" onclick="ajaxActionUser(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
## USERS GROUPS
function ajaxActionUsersGroup(users_group_id,field_id){
var sUrl = "${h.url('delete_repo_users_group',repo_name=c.repo_name)}";
alert("${_('Failed to remove users group')}");},};
var postData = '_method=delete&users_group_id='+users_group_id;
%for g2p in c.repo_info.users_group_to_perm:
<tr id="id${id(g2p.users_group.users_group_name)}">
<td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.none')}</td>
<td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.read')}</td>
<td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.write')}</td>
<td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.admin')}</td>
<td><img style="vertical-align:bottom" src="/images/icons/group.png"/>${g2p.users_group.users_group_name}</td>
<span class="delete_icon action_button" onclick="ajaxActionUsersGroup(${g2p.users_group.users_group_id},'${'id%s'%id(g2p.users_group.users_group_name)}')">
\ No newline at end of file
@@ -99,13 +99,13 @@
<!-- 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 by Marcin Kuzminski</p>
<p>RhodeCode ${c.rhodecode_version} © 2010-2011 by Marcin Kuzminski</p>
function tooltip_activate(){
${h.tooltip.activate()}
}
@@ -53,82 +53,14 @@
<label for="">${_('Permissions')}:</label>
<td>${_('user')}</td>
<td>${h.radio('perm_new_user','repository.none')}</td>
<td>${h.radio('perm_new_user','repository.read')}</td>
<td>${h.radio('perm_new_user','repository.write')}</td>
<td>${h.radio('perm_new_user','repository.admin')}</td>
${h.text('perm_new_user_name',class_='yui-ac-input')}
${_('Add another user')}
<%include file="../admin/repos/repo_edit_perms.html"/>
${h.submit('update','Update',class_="ui-button")}
Status change: