@@ -73,6 +73,11 @@ def make_map(config):
m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
action="delete_perm_user", conditions=dict(method=["DELETE"],
function=check_repo))
#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"],
@@ -215,8 +215,8 @@ class ReposController(BaseController):
@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:
@@ -229,9 +229,24 @@ class ReposController(BaseController):
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
try:
repo_model = RepoModel()
repo_model.delete_perm_users_group(request.POST, repo_name)
except Exception, e:
h.flash(_('An error occurred during deletion of repository'
' users groups'),
category='error')
"""DELETE an existing repository statistics
@@ -245,8 +260,8 @@ class ReposController(BaseController):
def repo_cache(self, repo_name):
INVALIDATE existing repository cache
"""INVALIDATE existing repository cache
@@ -267,8 +282,9 @@ class ReposController(BaseController):
"""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'
@@ -293,7 +309,12 @@ class ReposController(BaseController):
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})
else:
@@ -301,11 +322,15 @@ class ReposController(BaseController):
.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(
@@ -41,6 +41,7 @@ from rhodecode.lib.base import BaseContr
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__)
@@ -62,12 +63,28 @@ class SettingsController(BaseController)
return redirect(url('home'))
replacement_user = self.sa.query(User)\
@@ -202,6 +202,7 @@ class Repository(Base, BaseModel):
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')
@@ -246,24 +246,25 @@ class ValidPerms(formencode.validators.F
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
@@ -352,8 +353,10 @@ class AttrLoginValidator(formencode.vali
def to_python(self, value, state):
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
@@ -255,6 +255,19 @@ class RepoModel(BaseModel):
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()
self.sa.commit()
except:
log.error(traceback.format_exc())
def delete_stats(self, repo_name):
self.sa.query(Statistics)\
@@ -93,76 +93,8 @@
<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")}
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
@@ -102,7 +102,7 @@
<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>
@@ -56,76 +56,8 @@
<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: