##// END OF EJS Templates
caches: use individual namespaces per user to prevent beaker caching problems....
caches: use individual namespaces per user to prevent beaker caching problems. - especially for mysql in case large number of data in caches there could be critical errors storing cache, and thus preventing users from authentication. This is caused by the fact that we used single namespace for ALL users. It means it grew as number of users grew reaching mysql single column limit. This changes the behaviour and now we use namespace per-user it means that each user-id will have it's own cache namespace fragmenting maximum column data to a single user cache. Which we should never reach.

File last commit:

r2491:679204a0 default
r2591:36829a17 stable
Show More
repo_group_api.py
719 lines | 23.8 KiB | text/x-python | PythonLexer
project: added all source files and assets
r1 # -*- coding: utf-8 -*-
release: update copyright year to 2018
r2487 # Copyright (C) 2011-2018 RhodeCode GmbH
project: added all source files and assets
r1 #
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# 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 Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import logging
repo-group-schemas: refactor repository group schemas....
r1154 from rhodecode.api import JSONRPCValidationError
from rhodecode.api import jsonrpc_method, JSONRPCError
project: added all source files and assets
r1 from rhodecode.api.utils import (
has_superadmin_permission, Optional, OAttr, get_user_or_error,
repo-group-schemas: refactor repository group schemas....
r1154 get_repo_group_or_error, get_perm_or_error, get_user_group_or_error,
get_origin, validate_repo_group_permissions, validate_set_owner_permissions)
audit-logs: implemented full audit logs across application....
r1829 from rhodecode.lib import audit_logger
project: added all source files and assets
r1 from rhodecode.lib.auth import (
repo-group-schemas: refactor repository group schemas....
r1154 HasRepoGroupPermissionAnyApi, HasUserGroupPermissionAnyApi)
from rhodecode.model.db import Session
project: added all source files and assets
r1 from rhodecode.model.repo_group import RepoGroupModel
from rhodecode.model.scm import RepoGroupList
repo-group-schemas: refactor repository group schemas....
r1154 from rhodecode.model import validation_schema
gists: use colander schema to validate input data....
r523 from rhodecode.model.validation_schema.schemas import repo_group_schema
project: added all source files and assets
r1
log = logging.getLogger(__name__)
@jsonrpc_method()
def get_repo_group(request, apiuser, repogroupid):
"""
Return the specified |repo| group, along with permissions,
and repositories inside the group
:param apiuser: This is filled automatically from the |authtoken|.
:type apiuser: AuthUser
:param repogroupid: Specify the name of ID of the repository group.
:type repogroupid: str or int
Example output:
.. code-block:: bash
{
"error": null,
"id": repo-group-id,
"result": {
"group_description": "repo group description",
"group_id": 14,
"group_name": "group name",
api: fixed tests and update docstrings.
r2438 "permissions": [
project: added all source files and assets
r1 {
"name": "super-admin-username",
"origin": "super-admin",
"permission": "group.admin",
"type": "user"
},
{
"name": "owner-name",
"origin": "owner",
"permission": "group.admin",
"type": "user"
},
{
"name": "user-group-name",
"origin": "permission",
"permission": "group.write",
"type": "user_group"
}
],
"owner": "owner-name",
"parent_group": null,
"repositories": [ repo-list ]
}
}
"""
repo_group = get_repo_group_or_error(repogroupid)
if not has_superadmin_permission(apiuser):
# check if we have at least read permission for this repo group !
_perms = ('group.admin', 'group.write', 'group.read',)
if not HasRepoGroupPermissionAnyApi(*_perms)(
user=apiuser, group_name=repo_group.group_name):
raise JSONRPCError(
'repository group `%s` does not exist' % (repogroupid,))
permissions = []
for _user in repo_group.permissions():
user_data = {
'name': _user.username,
'permission': _user.permission,
'origin': get_origin(_user),
'type': "user",
}
permissions.append(user_data)
for _user_group in repo_group.permission_user_groups():
user_group_data = {
'name': _user_group.users_group_name,
'permission': _user_group.permission,
'origin': get_origin(_user_group),
'type': "user_group",
}
permissions.append(user_group_data)
data = repo_group.get_api_data()
api: deprecation, of members attribute that is replaced now with permissions returning a set of permissions...
r2436 data["permissions"] = permissions
project: added all source files and assets
r1 return data
@jsonrpc_method()
def get_repo_groups(request, apiuser):
"""
Returns all repository groups.
:param apiuser: This is filled automatically from the |authtoken|.
:type apiuser: AuthUser
"""
result = []
_perms = ('group.read', 'group.write', 'group.admin',)
extras = {'user': apiuser}
for repo_group in RepoGroupList(RepoGroupModel().get_all(),
perm_set=_perms, extra_kwargs=extras):
result.append(repo_group.get_api_data())
return result
@jsonrpc_method()
repo-group-schemas: refactor repository group schemas....
r1154 def create_repo_group(
request, apiuser, group_name,
owner=Optional(OAttr('apiuser')),
description=Optional(''),
copy_permissions=Optional(False)):
project: added all source files and assets
r1 """
Creates a repository group.
repo-group-schemas: refactor repository group schemas....
r1154 * If the repository group name contains "/", repository group will be
created inside a repository group or nested repository groups
project: added all source files and assets
r1
repo-group-schemas: refactor repository group schemas....
r1154 For example "foo/bar/group1" will create repository group called "group1"
inside group "foo/bar". You have to have permissions to access and
write to the last repository group ("bar" in this example)
project: added all source files and assets
r1
repo-group-schemas: refactor repository group schemas....
r1154 This command can only be run using an |authtoken| with at least
permissions to create repository groups, or admin permissions to
parent repository groups.
project: added all source files and assets
r1
:param apiuser: This is filled automatically from the |authtoken|.
:type apiuser: AuthUser
:param group_name: Set the repository group name.
:type group_name: str
:param description: Set the |repo| group description.
:type description: str
:param owner: Set the |repo| group owner.
:type owner: str
:param copy_permissions:
:type copy_permissions:
Example output:
.. code-block:: bash
id : <id_given_in_input>
result : {
"msg": "Created new repo group `<repo_group_name>`"
"repo_group": <repogroup_object>
}
error : null
Example error output:
.. code-block:: bash
id : <id_given_in_input>
result : null
error : {
failed to create repo group `<repogroupid>`
}
"""
repo-group-schemas: refactor repository group schemas....
r1154 owner = validate_set_owner_permissions(apiuser, owner)
project: added all source files and assets
r1
repo-group-schemas: refactor repository group schemas....
r1154 description = Optional.extract(description)
project: added all source files and assets
r1 copy_permissions = Optional.extract(copy_permissions)
repo-group-schemas: refactor repository group schemas....
r1154 schema = repo_group_schema.RepoGroupSchema().bind(
# user caller
user=apiuser)
project: added all source files and assets
r1
repo-group-schemas: refactor repository group schemas....
r1154 try:
schema_data = schema.deserialize(dict(
repo_group_name=group_name,
repo_group_owner=owner.username,
repo_group_description=description,
repo_group_copy_permissions=copy_permissions,
))
except validation_schema.Invalid as err:
raise JSONRPCValidationError(colander_exc=err)
project: added all source files and assets
r1
repo-group-schemas: refactor repository group schemas....
r1154 validated_group_name = schema_data['repo_group_name']
project: added all source files and assets
r1
try:
repo_group = RepoGroupModel().create(
owner=owner,
repo-group-schemas: refactor repository group schemas....
r1154 group_name=validated_group_name,
api: fixed problem with setting repo group description via API....
r2491 group_description=schema_data['repo_group_description'],
repo-group-schemas: refactor repository group schemas....
r1154 copy_permissions=schema_data['repo_group_copy_permissions'])
audit-logs: implemented full audit logs across application....
r1829 Session().flush()
repo_group_data = repo_group.get_api_data()
audit_logger.store_api(
'repo_group.create', action_data={'data': repo_group_data},
user=apiuser)
project: added all source files and assets
r1 Session().commit()
return {
repo-group-schemas: refactor repository group schemas....
r1154 'msg': 'Created new repo group `%s`' % validated_group_name,
project: added all source files and assets
r1 'repo_group': repo_group.get_api_data()
}
except Exception:
log.exception("Exception occurred while trying create repo group")
raise JSONRPCError(
repo-group-schemas: refactor repository group schemas....
r1154 'failed to create repo group `%s`' % (validated_group_name,))
project: added all source files and assets
r1
@jsonrpc_method()
def update_repo_group(
request, apiuser, repogroupid, group_name=Optional(''),
description=Optional(''), owner=Optional(OAttr('apiuser')),
repo-group-schemas: refactor repository group schemas....
r1154 enable_locking=Optional(False)):
project: added all source files and assets
r1 """
Updates repository group with the details given.
This command can only be run using an |authtoken| with admin
permissions.
repo-group-schemas: refactor repository group schemas....
r1154 * If the group_name name contains "/", repository group will be updated
accordingly with a repository group or nested repository groups
For example repogroupid=group-test group_name="foo/bar/group-test"
will update repository group called "group-test" and place it
inside group "foo/bar".
You have to have permissions to access and write to the last repository
group ("bar" in this example)
project: added all source files and assets
r1 :param apiuser: This is filled automatically from the |authtoken|.
:type apiuser: AuthUser
:param repogroupid: Set the ID of repository group.
:type repogroupid: str or int
:param group_name: Set the name of the |repo| group.
:type group_name: str
:param description: Set a description for the group.
:type description: str
:param owner: Set the |repo| group owner.
:type owner: str
:param enable_locking: Enable |repo| locking. The default is false.
:type enable_locking: bool
"""
repo_group = get_repo_group_or_error(repogroupid)
repo-group-schemas: refactor repository group schemas....
r1154
project: added all source files and assets
r1 if not has_superadmin_permission(apiuser):
repo-group-schemas: refactor repository group schemas....
r1154 validate_repo_group_permissions(
apiuser, repogroupid, repo_group, ('group.admin',))
updates = dict(
group_name=group_name
if not isinstance(group_name, Optional) else repo_group.group_name,
group_description=description
if not isinstance(description, Optional) else repo_group.group_description,
user=owner
if not isinstance(owner, Optional) else repo_group.user.username,
enable_locking=enable_locking
if not isinstance(enable_locking, Optional) else repo_group.enable_locking
)
project: added all source files and assets
r1
repo-group-schemas: refactor repository group schemas....
r1154 schema = repo_group_schema.RepoGroupSchema().bind(
# user caller
user=apiuser,
old_values=repo_group.get_api_data())
project: added all source files and assets
r1 try:
repo-group-schemas: refactor repository group schemas....
r1154 schema_data = schema.deserialize(dict(
repo_group_name=updates['group_name'],
repo_group_owner=updates['user'],
repo_group_description=updates['group_description'],
repo_group_enable_locking=updates['enable_locking'],
))
except validation_schema.Invalid as err:
raise JSONRPCValidationError(colander_exc=err)
validated_updates = dict(
group_name=schema_data['repo_group']['repo_group_name_without_group'],
group_parent_id=schema_data['repo_group']['repo_group_id'],
user=schema_data['repo_group_owner'],
group_description=schema_data['repo_group_description'],
enable_locking=schema_data['repo_group_enable_locking'],
)
audit-logs: implemented full audit logs across application....
r1829 old_data = repo_group.get_api_data()
repo-group-schemas: refactor repository group schemas....
r1154 try:
RepoGroupModel().update(repo_group, validated_updates)
audit-logs: implemented full audit logs across application....
r1829 audit_logger.store_api(
'repo_group.edit', action_data={'old_data': old_data},
user=apiuser)
project: added all source files and assets
r1 Session().commit()
return {
'msg': 'updated repository group ID:%s %s' % (
repo_group.group_id, repo_group.group_name),
'repo_group': repo_group.get_api_data()
}
except Exception:
repo-group-schemas: refactor repository group schemas....
r1154 log.exception(
u"Exception occurred while trying update repo group %s",
repogroupid)
project: added all source files and assets
r1 raise JSONRPCError('failed to update repository group `%s`'
% (repogroupid,))
@jsonrpc_method()
def delete_repo_group(request, apiuser, repogroupid):
"""
Deletes a |repo| group.
:param apiuser: This is filled automatically from the |authtoken|.
:type apiuser: AuthUser
:param repogroupid: Set the name or ID of repository group to be
deleted.
:type repogroupid: str or int
Example output:
.. code-block:: bash
id : <id_given_in_input>
result : {
docs: fixed small wanrings/errors during build.
r1120 'msg': 'deleted repo group ID:<repogroupid> <repogroupname>'
project: added all source files and assets
r1 'repo_group': null
}
error : null
Example error output:
.. code-block:: bash
id : <id_given_in_input>
result : null
error : {
"failed to delete repo group ID:<repogroupid> <repogroupname>"
}
"""
repo_group = get_repo_group_or_error(repogroupid)
if not has_superadmin_permission(apiuser):
repo-group-schemas: refactor repository group schemas....
r1154 validate_repo_group_permissions(
apiuser, repogroupid, repo_group, ('group.admin',))
audit-logs: implemented full audit logs across application....
r1829 old_data = repo_group.get_api_data()
project: added all source files and assets
r1 try:
RepoGroupModel().delete(repo_group)
audit-logs: implemented full audit logs across application....
r1829 audit_logger.store_api(
'repo_group.delete', action_data={'old_data': old_data},
user=apiuser)
project: added all source files and assets
r1 Session().commit()
return {
'msg': 'deleted repo group ID:%s %s' %
(repo_group.group_id, repo_group.group_name),
'repo_group': None
}
except Exception:
log.exception("Exception occurred while trying to delete repo group")
raise JSONRPCError('failed to delete repo group ID:%s %s' %
(repo_group.group_id, repo_group.group_name))
@jsonrpc_method()
def grant_user_permission_to_repo_group(
request, apiuser, repogroupid, userid, perm,
apply_to_children=Optional('none')):
"""
Grant permission for a user on the given repository group, or update
existing permissions if found.
This command can only be run using an |authtoken| with admin
permissions.
:param apiuser: This is filled automatically from the |authtoken|.
:type apiuser: AuthUser
:param repogroupid: Set the name or ID of repository group.
:type repogroupid: str or int
:param userid: Set the user name.
:type userid: str
:param perm: (group.(none|read|write|admin))
:type perm: str
:param apply_to_children: 'none', 'repos', 'groups', 'all'
:type apply_to_children: str
Example output:
.. code-block:: bash
id : <id_given_in_input>
result: {
"msg" : "Granted perm: `<perm>` (recursive:<apply_to_children>) for user: `<username>` in repo group: `<repo_group_name>`",
"success": true
}
error: null
Example error output:
.. code-block:: bash
id : <id_given_in_input>
result : null
error : {
"failed to edit permission for user: `<userid>` in repo group: `<repo_group_name>`"
}
"""
repo_group = get_repo_group_or_error(repogroupid)
if not has_superadmin_permission(apiuser):
repo-group-schemas: refactor repository group schemas....
r1154 validate_repo_group_permissions(
apiuser, repogroupid, repo_group, ('group.admin',))
project: added all source files and assets
r1
user = get_user_or_error(userid)
perm = get_perm_or_error(perm, prefix='group.')
apply_to_children = Optional.extract(apply_to_children)
perm_additions = [[user.user_id, perm, "user"]]
try:
RepoGroupModel().update_permissions(repo_group=repo_group,
perm_additions=perm_additions,
recursive=apply_to_children,
cur_user=apiuser)
Session().commit()
return {
'msg': 'Granted perm: `%s` (recursive:%s) for user: '
'`%s` in repo group: `%s`' % (
perm.permission_name, apply_to_children, user.username,
repo_group.name
),
'success': True
}
except Exception:
log.exception("Exception occurred while trying to grant "
"user permissions to repo group")
raise JSONRPCError(
'failed to edit permission for user: '
'`%s` in repo group: `%s`' % (userid, repo_group.name))
@jsonrpc_method()
def revoke_user_permission_from_repo_group(
request, apiuser, repogroupid, userid,
apply_to_children=Optional('none')):
"""
Revoke permission for a user in a given repository group.
This command can only be run using an |authtoken| with admin
permissions on the |repo| group.
:param apiuser: This is filled automatically from the |authtoken|.
:type apiuser: AuthUser
:param repogroupid: Set the name or ID of the repository group.
:type repogroupid: str or int
:param userid: Set the user name to revoke.
:type userid: str
:param apply_to_children: 'none', 'repos', 'groups', 'all'
:type apply_to_children: str
Example output:
.. code-block:: bash
id : <id_given_in_input>
result: {
"msg" : "Revoked perm (recursive:<apply_to_children>) for user: `<username>` in repo group: `<repo_group_name>`",
"success": true
}
error: null
Example error output:
.. code-block:: bash
id : <id_given_in_input>
result : null
error : {
"failed to edit permission for user: `<userid>` in repo group: `<repo_group_name>`"
}
"""
repo_group = get_repo_group_or_error(repogroupid)
if not has_superadmin_permission(apiuser):
repo-group-schemas: refactor repository group schemas....
r1154 validate_repo_group_permissions(
apiuser, repogroupid, repo_group, ('group.admin',))
project: added all source files and assets
r1
user = get_user_or_error(userid)
apply_to_children = Optional.extract(apply_to_children)
perm_deletions = [[user.user_id, None, "user"]]
try:
RepoGroupModel().update_permissions(repo_group=repo_group,
perm_deletions=perm_deletions,
recursive=apply_to_children,
cur_user=apiuser)
Session().commit()
return {
'msg': 'Revoked perm (recursive:%s) for user: '
'`%s` in repo group: `%s`' % (
apply_to_children, user.username, repo_group.name
),
'success': True
}
except Exception:
log.exception("Exception occurred while trying revoke user "
"permission from repo group")
raise JSONRPCError(
'failed to edit permission for user: '
'`%s` in repo group: `%s`' % (userid, repo_group.name))
@jsonrpc_method()
def grant_user_group_permission_to_repo_group(
request, apiuser, repogroupid, usergroupid, perm,
apply_to_children=Optional('none'), ):
"""
Grant permission for a user group on given repository group, or update
existing permissions if found.
This command can only be run using an |authtoken| with admin
permissions on the |repo| group.
:param apiuser: This is filled automatically from the |authtoken|.
:type apiuser: AuthUser
:param repogroupid: Set the name or id of repository group
:type repogroupid: str or int
:param usergroupid: id of usergroup
:type usergroupid: str or int
:param perm: (group.(none|read|write|admin))
:type perm: str
:param apply_to_children: 'none', 'repos', 'groups', 'all'
:type apply_to_children: str
Example output:
.. code-block:: bash
id : <id_given_in_input>
result : {
"msg" : "Granted perm: `<perm>` (recursive:<apply_to_children>) for user group: `<usersgroupname>` in repo group: `<repo_group_name>`",
"success": true
}
error : null
Example error output:
.. code-block:: bash
id : <id_given_in_input>
result : null
error : {
"failed to edit permission for user group: `<usergroup>` in repo group: `<repo_group_name>`"
}
"""
repo_group = get_repo_group_or_error(repogroupid)
perm = get_perm_or_error(perm, prefix='group.')
user_group = get_user_group_or_error(usergroupid)
if not has_superadmin_permission(apiuser):
repo-group-schemas: refactor repository group schemas....
r1154 validate_repo_group_permissions(
apiuser, repogroupid, repo_group, ('group.admin',))
project: added all source files and assets
r1
# check if we have at least read permission for this user group !
_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',)
if not HasUserGroupPermissionAnyApi(*_perms)(
user=apiuser, user_group_name=user_group.users_group_name):
raise JSONRPCError(
'user group `%s` does not exist' % (usergroupid,))
apply_to_children = Optional.extract(apply_to_children)
perm_additions = [[user_group.users_group_id, perm, "user_group"]]
try:
RepoGroupModel().update_permissions(repo_group=repo_group,
perm_additions=perm_additions,
recursive=apply_to_children,
cur_user=apiuser)
Session().commit()
return {
'msg': 'Granted perm: `%s` (recursive:%s) '
'for user group: `%s` in repo group: `%s`' % (
perm.permission_name, apply_to_children,
user_group.users_group_name, repo_group.name
),
'success': True
}
except Exception:
log.exception("Exception occurred while trying to grant user "
"group permissions to repo group")
raise JSONRPCError(
'failed to edit permission for user group: `%s` in '
'repo group: `%s`' % (
usergroupid, repo_group.name
)
)
@jsonrpc_method()
def revoke_user_group_permission_from_repo_group(
request, apiuser, repogroupid, usergroupid,
apply_to_children=Optional('none')):
"""
Revoke permission for user group on given repository.
This command can only be run using an |authtoken| with admin
permissions on the |repo| group.
:param apiuser: This is filled automatically from the |authtoken|.
:type apiuser: AuthUser
:param repogroupid: name or id of repository group
:type repogroupid: str or int
:param usergroupid:
:param apply_to_children: 'none', 'repos', 'groups', 'all'
:type apply_to_children: str
Example output:
.. code-block:: bash
id : <id_given_in_input>
result: {
"msg" : "Revoked perm (recursive:<apply_to_children>) for user group: `<usersgroupname>` in repo group: `<repo_group_name>`",
"success": true
}
error: null
Example error output:
.. code-block:: bash
id : <id_given_in_input>
result : null
error : {
"failed to edit permission for user group: `<usergroup>` in repo group: `<repo_group_name>`"
}
"""
repo_group = get_repo_group_or_error(repogroupid)
user_group = get_user_group_or_error(usergroupid)
if not has_superadmin_permission(apiuser):
repo-group-schemas: refactor repository group schemas....
r1154 validate_repo_group_permissions(
apiuser, repogroupid, repo_group, ('group.admin',))
project: added all source files and assets
r1
# check if we have at least read permission for this user group !
_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',)
if not HasUserGroupPermissionAnyApi(*_perms)(
user=apiuser, user_group_name=user_group.users_group_name):
raise JSONRPCError(
'user group `%s` does not exist' % (usergroupid,))
apply_to_children = Optional.extract(apply_to_children)
perm_deletions = [[user_group.users_group_id, None, "user_group"]]
try:
RepoGroupModel().update_permissions(repo_group=repo_group,
perm_deletions=perm_deletions,
recursive=apply_to_children,
cur_user=apiuser)
Session().commit()
return {
'msg': 'Revoked perm (recursive:%s) for user group: '
'`%s` in repo group: `%s`' % (
apply_to_children, user_group.users_group_name,
repo_group.name
),
'success': True
}
except Exception:
log.exception("Exception occurred while trying revoke user group "
"permissions from repo group")
raise JSONRPCError(
'failed to edit permission for user group: '
'`%s` in repo group: `%s`' % (
user_group.users_group_name, repo_group.name
)
)