# HG changeset patch # User Marcin Kuzminski # Date 2017-06-21 11:28:12 # Node ID 87ca65d79bcb031720102b5e3675444e628fc6b4 # Parent d786fdd7cf0f643f07f287f590f6d324dd5f4a72 user-group-api: use simple schema validator to be consistent how we validate user group names during creation between API and WEB. diff --git a/rhodecode/api/tests/test_create_user_group.py b/rhodecode/api/tests/test_create_user_group.py --- a/rhodecode/api/tests/test_create_user_group.py +++ b/rhodecode/api/tests/test_create_user_group.py @@ -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) diff --git a/rhodecode/api/views/user_group_api.py b/rhodecode/api/views/user_group_api.py --- a/rhodecode/api/views/user_group_api.py +++ b/rhodecode/api/views/user_group_api.py @@ -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 Use 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( diff --git a/rhodecode/model/validation_schema/schemas/user_group_schema.py b/rhodecode/model/validation_schema/schemas/user_group_schema.py new file mode 100644 --- /dev/null +++ b/rhodecode/model/validation_schema/schemas/user_group_schema.py @@ -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 . +# +# 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