user-group-api: use simple schema validator to be consistent how we validate
user group names during creation between API and WEB.
This commit is contained in:
parent
af07c911dc
commit
749f784ad9
3 changed files with 119 additions and 9 deletions
|
|
@ -112,3 +112,16 @@ class TestCreateUserGroup(object):
|
|||
|
||||
expected = 'failed to create group `%s`' % (group_name,)
|
||||
assert_error(id_, expected, given=response.body)
|
||||
|
||||
def test_api_create_user_group_with_wrong_name(self, user_util):
|
||||
|
||||
group_name = 'wrong NAME <>'
|
||||
id_, params = build_data(
|
||||
self.apikey, 'create_user_group', group_name=group_name)
|
||||
response = api_call(self.app, params)
|
||||
|
||||
expected = {"user_group_name":
|
||||
"Allowed in name are letters, numbers, and `-`, `_`, "
|
||||
"`.` Name must start with a letter or number. "
|
||||
"Got `{}`".format(group_name)}
|
||||
assert_error(id_, expected, given=response.body)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@
|
|||
|
||||
import logging
|
||||
|
||||
from rhodecode.api import jsonrpc_method, JSONRPCError, JSONRPCForbidden
|
||||
from rhodecode.api import jsonrpc_method, JSONRPCError, JSONRPCForbidden, \
|
||||
JSONRPCValidationError
|
||||
from rhodecode.api.utils import (
|
||||
Optional, OAttr, store_update, has_superadmin_permission, get_origin,
|
||||
get_user_or_error, get_user_group_or_error, get_perm_or_error)
|
||||
|
|
@ -30,6 +31,8 @@ from rhodecode.lib.exceptions import UserGroupAssignedException
|
|||
from rhodecode.model.db import Session
|
||||
from rhodecode.model.scm import UserGroupList
|
||||
from rhodecode.model.user_group import UserGroupModel
|
||||
from rhodecode.model import validation_schema
|
||||
from rhodecode.model.validation_schema.schemas import user_group_schema
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -211,16 +214,32 @@ def create_user_group(
|
|||
if UserGroupModel().get_by_name(group_name):
|
||||
raise JSONRPCError("user group `%s` already exist" % (group_name,))
|
||||
|
||||
try:
|
||||
if isinstance(owner, Optional):
|
||||
owner = apiuser.user_id
|
||||
if isinstance(owner, Optional):
|
||||
owner = apiuser.user_id
|
||||
|
||||
owner = get_user_or_error(owner)
|
||||
active = Optional.extract(active)
|
||||
description = Optional.extract(description)
|
||||
owner = get_user_or_error(owner)
|
||||
active = Optional.extract(active)
|
||||
description = Optional.extract(description)
|
||||
|
||||
schema = user_group_schema.UserGroupSchema().bind(
|
||||
# user caller
|
||||
user=apiuser)
|
||||
try:
|
||||
schema_data = schema.deserialize(dict(
|
||||
user_group_name=group_name,
|
||||
user_group_description=description,
|
||||
user_group_owner=owner.username,
|
||||
user_group_active=active,
|
||||
))
|
||||
except validation_schema.Invalid as err:
|
||||
raise JSONRPCValidationError(colander_exc=err)
|
||||
|
||||
try:
|
||||
user_group = UserGroupModel().create(
|
||||
name=group_name, description=description, owner=owner,
|
||||
active=active)
|
||||
name=schema_data['user_group_name'],
|
||||
description=schema_data['user_group_description'],
|
||||
owner=owner,
|
||||
active=schema_data['user_group_active'])
|
||||
Session().flush()
|
||||
creation_data = user_group.get_api_data()
|
||||
audit_logger.store_api(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2016-2017 RhodeCode GmbH
|
||||
#
|
||||
# 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 re
|
||||
import colander
|
||||
|
||||
from rhodecode.model.validation_schema import types, validators
|
||||
from rhodecode.translation import _
|
||||
|
||||
|
||||
@colander.deferred
|
||||
def deferred_user_group_name_validator(node, kw):
|
||||
|
||||
def name_validator(node, value):
|
||||
|
||||
msg = _('Allowed in name are letters, numbers, and `-`, `_`, `.` '
|
||||
'Name must start with a letter or number. Got `{}`').format(value)
|
||||
|
||||
if not re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value):
|
||||
raise colander.Invalid(node, msg)
|
||||
|
||||
return name_validator
|
||||
|
||||
|
||||
@colander.deferred
|
||||
def deferred_user_group_owner_validator(node, kw):
|
||||
|
||||
def owner_validator(node, value):
|
||||
from rhodecode.model.db import User
|
||||
existing = User.get_by_username(value)
|
||||
if not existing:
|
||||
msg = _(u'User group owner with id `{}` does not exists').format(value)
|
||||
raise colander.Invalid(node, msg)
|
||||
|
||||
return owner_validator
|
||||
|
||||
|
||||
class UserGroupSchema(colander.Schema):
|
||||
|
||||
user_group_name = colander.SchemaNode(
|
||||
colander.String(),
|
||||
validator=deferred_user_group_name_validator)
|
||||
|
||||
user_group_description = colander.SchemaNode(
|
||||
colander.String(), missing='')
|
||||
|
||||
user_group_owner = colander.SchemaNode(
|
||||
colander.String(),
|
||||
validator=deferred_user_group_owner_validator)
|
||||
|
||||
user_group_active = colander.SchemaNode(
|
||||
types.StringBooleanType(),
|
||||
missing=False)
|
||||
|
||||
def deserialize(self, cstruct):
|
||||
"""
|
||||
Custom deserialize that allows to chain validation, and verify
|
||||
permissions, and as last step uniqueness
|
||||
"""
|
||||
|
||||
appstruct = super(UserGroupSchema, self).deserialize(cstruct)
|
||||
return appstruct
|
||||
Loading…
Add table
Add a link
Reference in a new issue