##// END OF EJS Templates
fixes issue #702 API methods without arguments fail when "args":null
marcink -
r3165:e1baadec beta
parent child Browse files
Show More
@@ -1,292 +1,296 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.api
3 rhodecode.controllers.api
4 ~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 JSON RPC controller
6 JSON RPC controller
7
7
8 :created_on: Aug 20, 2011
8 :created_on: Aug 20, 2011
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software; you can redistribute it and/or
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
16 # of the License or (at your opinion) any later version of the license.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
26 # MA 02110-1301, USA.
27
27
28 import inspect
28 import inspect
29 import logging
29 import logging
30 import types
30 import types
31 import urllib
31 import urllib
32 import traceback
32 import traceback
33 import time
33 import time
34
34
35 from paste.response import replace_header
35 from paste.response import replace_header
36 from pylons.controllers import WSGIController
36 from pylons.controllers import WSGIController
37
37
38 from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \
38 from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \
39 HTTPBadRequest, HTTPError
39 HTTPBadRequest, HTTPError
40
40
41 from rhodecode.model.db import User
41 from rhodecode.model.db import User
42 from rhodecode.model import meta
42 from rhodecode.model import meta
43 from rhodecode.lib.compat import izip_longest, json
43 from rhodecode.lib.compat import izip_longest, json
44 from rhodecode.lib.auth import AuthUser
44 from rhodecode.lib.auth import AuthUser
45 from rhodecode.lib.base import _get_ip_addr, _get_access_path
45 from rhodecode.lib.base import _get_ip_addr, _get_access_path
46 from rhodecode.lib.utils2 import safe_unicode
46 from rhodecode.lib.utils2 import safe_unicode
47
47
48 log = logging.getLogger('JSONRPC')
48 log = logging.getLogger('JSONRPC')
49
49
50
50
51 class JSONRPCError(BaseException):
51 class JSONRPCError(BaseException):
52
52
53 def __init__(self, message):
53 def __init__(self, message):
54 self.message = message
54 self.message = message
55 super(JSONRPCError, self).__init__()
55 super(JSONRPCError, self).__init__()
56
56
57 def __str__(self):
57 def __str__(self):
58 return str(self.message)
58 return str(self.message)
59
59
60
60
61 def jsonrpc_error(message, retid=None, code=None):
61 def jsonrpc_error(message, retid=None, code=None):
62 """
62 """
63 Generate a Response object with a JSON-RPC error body
63 Generate a Response object with a JSON-RPC error body
64 """
64 """
65 from pylons.controllers.util import Response
65 from pylons.controllers.util import Response
66 return Response(
66 return Response(
67 body=json.dumps(dict(id=retid, result=None, error=message)),
67 body=json.dumps(dict(id=retid, result=None, error=message)),
68 status=code,
68 status=code,
69 content_type='application/json'
69 content_type='application/json'
70 )
70 )
71
71
72
72
73 class JSONRPCController(WSGIController):
73 class JSONRPCController(WSGIController):
74 """
74 """
75 A WSGI-speaking JSON-RPC controller class
75 A WSGI-speaking JSON-RPC controller class
76
76
77 See the specification:
77 See the specification:
78 <http://json-rpc.org/wiki/specification>`.
78 <http://json-rpc.org/wiki/specification>`.
79
79
80 Valid controller return values should be json-serializable objects.
80 Valid controller return values should be json-serializable objects.
81
81
82 Sub-classes should catch their exceptions and raise JSONRPCError
82 Sub-classes should catch their exceptions and raise JSONRPCError
83 if they want to pass meaningful errors to the client.
83 if they want to pass meaningful errors to the client.
84
84
85 """
85 """
86
86
87 def _get_ip_addr(self, environ):
87 def _get_ip_addr(self, environ):
88 return _get_ip_addr(environ)
88 return _get_ip_addr(environ)
89
89
90 def _get_method_args(self):
90 def _get_method_args(self):
91 """
91 """
92 Return `self._rpc_args` to dispatched controller method
92 Return `self._rpc_args` to dispatched controller method
93 chosen by __call__
93 chosen by __call__
94 """
94 """
95 return self._rpc_args
95 return self._rpc_args
96
96
97 def __call__(self, environ, start_response):
97 def __call__(self, environ, start_response):
98 """
98 """
99 Parse the request body as JSON, look up the method on the
99 Parse the request body as JSON, look up the method on the
100 controller and if it exists, dispatch to it.
100 controller and if it exists, dispatch to it.
101 """
101 """
102 start = time.time()
102 start = time.time()
103 ip_addr = self.ip_addr = self._get_ip_addr(environ)
103 ip_addr = self.ip_addr = self._get_ip_addr(environ)
104 self._req_id = None
104 self._req_id = None
105 if 'CONTENT_LENGTH' not in environ:
105 if 'CONTENT_LENGTH' not in environ:
106 log.debug("No Content-Length")
106 log.debug("No Content-Length")
107 return jsonrpc_error(retid=self._req_id,
107 return jsonrpc_error(retid=self._req_id,
108 message="No Content-Length in request")
108 message="No Content-Length in request")
109 else:
109 else:
110 length = environ['CONTENT_LENGTH'] or 0
110 length = environ['CONTENT_LENGTH'] or 0
111 length = int(environ['CONTENT_LENGTH'])
111 length = int(environ['CONTENT_LENGTH'])
112 log.debug('Content-Length: %s' % length)
112 log.debug('Content-Length: %s' % length)
113
113
114 if length == 0:
114 if length == 0:
115 log.debug("Content-Length is 0")
115 log.debug("Content-Length is 0")
116 return jsonrpc_error(retid=self._req_id,
116 return jsonrpc_error(retid=self._req_id,
117 message="Content-Length is 0")
117 message="Content-Length is 0")
118
118
119 raw_body = environ['wsgi.input'].read(length)
119 raw_body = environ['wsgi.input'].read(length)
120
120
121 try:
121 try:
122 json_body = json.loads(urllib.unquote_plus(raw_body))
122 json_body = json.loads(urllib.unquote_plus(raw_body))
123 except ValueError, e:
123 except ValueError, e:
124 # catch JSON errors Here
124 # catch JSON errors Here
125 return jsonrpc_error(retid=self._req_id,
125 return jsonrpc_error(retid=self._req_id,
126 message="JSON parse error ERR:%s RAW:%r" \
126 message="JSON parse error ERR:%s RAW:%r" \
127 % (e, urllib.unquote_plus(raw_body)))
127 % (e, urllib.unquote_plus(raw_body)))
128
128
129 # check AUTH based on API KEY
129 # check AUTH based on API KEY
130 try:
130 try:
131 self._req_api_key = json_body['api_key']
131 self._req_api_key = json_body['api_key']
132 self._req_id = json_body['id']
132 self._req_id = json_body['id']
133 self._req_method = json_body['method']
133 self._req_method = json_body['method']
134 self._request_params = json_body['args']
134 self._request_params = json_body['args']
135 if not isinstance(self._request_params, dict):
136 self._request_params = {}
137
135 log.debug(
138 log.debug(
136 'method: %s, params: %s' % (self._req_method,
139 'method: %s, params: %s' % (self._req_method,
137 self._request_params)
140 self._request_params)
138 )
141 )
139 except KeyError, e:
142 except KeyError, e:
140 return jsonrpc_error(retid=self._req_id,
143 return jsonrpc_error(retid=self._req_id,
141 message='Incorrect JSON query missing %s' % e)
144 message='Incorrect JSON query missing %s' % e)
142
145
143 # check if we can find this session using api_key
146 # check if we can find this session using api_key
144 try:
147 try:
145 u = User.get_by_api_key(self._req_api_key)
148 u = User.get_by_api_key(self._req_api_key)
146 if u is None:
149 if u is None:
147 return jsonrpc_error(retid=self._req_id,
150 return jsonrpc_error(retid=self._req_id,
148 message='Invalid API KEY')
151 message='Invalid API KEY')
149
152
150 #check if we are allowed to use this IP
153 #check if we are allowed to use this IP
151 auth_u = AuthUser(u.user_id, self._req_api_key, ip_addr=ip_addr)
154 auth_u = AuthUser(u.user_id, self._req_api_key, ip_addr=ip_addr)
152 if not auth_u.ip_allowed:
155 if not auth_u.ip_allowed:
153 return jsonrpc_error(retid=self._req_id,
156 return jsonrpc_error(retid=self._req_id,
154 message='request from IP:%s not allowed' % (ip_addr))
157 message='request from IP:%s not allowed' % (ip_addr))
155 else:
158 else:
156 log.info('Access for IP:%s allowed' % (ip_addr))
159 log.info('Access for IP:%s allowed' % (ip_addr))
157
160
158 except Exception, e:
161 except Exception, e:
159 return jsonrpc_error(retid=self._req_id,
162 return jsonrpc_error(retid=self._req_id,
160 message='Invalid API KEY')
163 message='Invalid API KEY')
161
164
162 self._error = None
165 self._error = None
163 try:
166 try:
164 self._func = self._find_method()
167 self._func = self._find_method()
165 except AttributeError, e:
168 except AttributeError, e:
166 return jsonrpc_error(retid=self._req_id,
169 return jsonrpc_error(retid=self._req_id,
167 message=str(e))
170 message=str(e))
168
171
169 # now that we have a method, add self._req_params to
172 # now that we have a method, add self._req_params to
170 # self.kargs and dispatch control to WGIController
173 # self.kargs and dispatch control to WGIController
171 argspec = inspect.getargspec(self._func)
174 argspec = inspect.getargspec(self._func)
172 arglist = argspec[0][1:]
175 arglist = argspec[0][1:]
173 defaults = map(type, argspec[3] or [])
176 defaults = map(type, argspec[3] or [])
174 default_empty = types.NotImplementedType
177 default_empty = types.NotImplementedType
175
178
176 # kw arguments required by this method
179 # kw arguments required by this method
177 func_kwargs = dict(izip_longest(reversed(arglist), reversed(defaults),
180 func_kwargs = dict(izip_longest(reversed(arglist), reversed(defaults),
178 fillvalue=default_empty))
181 fillvalue=default_empty))
179
182
180 # this is little trick to inject logged in user for
183 # this is little trick to inject logged in user for
181 # perms decorators to work they expect the controller class to have
184 # perms decorators to work they expect the controller class to have
182 # rhodecode_user attribute set
185 # rhodecode_user attribute set
183 self.rhodecode_user = auth_u
186 self.rhodecode_user = auth_u
184
187
185 # This attribute will need to be first param of a method that uses
188 # This attribute will need to be first param of a method that uses
186 # api_key, which is translated to instance of user at that name
189 # api_key, which is translated to instance of user at that name
187 USER_SESSION_ATTR = 'apiuser'
190 USER_SESSION_ATTR = 'apiuser'
188
191
189 if USER_SESSION_ATTR not in arglist:
192 if USER_SESSION_ATTR not in arglist:
190 return jsonrpc_error(
193 return jsonrpc_error(
191 retid=self._req_id,
194 retid=self._req_id,
192 message='This method [%s] does not support '
195 message='This method [%s] does not support '
193 'authentication (missing %s param)' % (
196 'authentication (missing %s param)' % (
194 self._func.__name__, USER_SESSION_ATTR)
197 self._func.__name__, USER_SESSION_ATTR)
195 )
198 )
196
199
197 # get our arglist and check if we provided them as args
200 # get our arglist and check if we provided them as args
198 for arg, default in func_kwargs.iteritems():
201 for arg, default in func_kwargs.iteritems():
199 if arg == USER_SESSION_ATTR:
202 if arg == USER_SESSION_ATTR:
200 # USER_SESSION_ATTR is something translated from api key and
203 # USER_SESSION_ATTR is something translated from api key and
201 # this is checked before so we don't need validate it
204 # this is checked before so we don't need validate it
202 continue
205 continue
203
206
204 # skip the required param check if it's default value is
207 # skip the required param check if it's default value is
205 # NotImplementedType (default_empty)
208 # NotImplementedType (default_empty)
206 if (default == default_empty and arg not in self._request_params):
209 if (default == default_empty and arg not in self._request_params):
207 return jsonrpc_error(
210 return jsonrpc_error(
208 retid=self._req_id,
211 retid=self._req_id,
209 message=(
212 message=(
210 'Missing non optional `%s` arg in JSON DATA' % arg
213 'Missing non optional `%s` arg in JSON DATA' % arg
211 )
214 )
212 )
215 )
213
216
214 self._rpc_args = {USER_SESSION_ATTR: u}
217 self._rpc_args = {USER_SESSION_ATTR: u}
218
215 self._rpc_args.update(self._request_params)
219 self._rpc_args.update(self._request_params)
216
220
217 self._rpc_args['action'] = self._req_method
221 self._rpc_args['action'] = self._req_method
218 self._rpc_args['environ'] = environ
222 self._rpc_args['environ'] = environ
219 self._rpc_args['start_response'] = start_response
223 self._rpc_args['start_response'] = start_response
220
224
221 status = []
225 status = []
222 headers = []
226 headers = []
223 exc_info = []
227 exc_info = []
224
228
225 def change_content(new_status, new_headers, new_exc_info=None):
229 def change_content(new_status, new_headers, new_exc_info=None):
226 status.append(new_status)
230 status.append(new_status)
227 headers.extend(new_headers)
231 headers.extend(new_headers)
228 exc_info.append(new_exc_info)
232 exc_info.append(new_exc_info)
229
233
230 output = WSGIController.__call__(self, environ, change_content)
234 output = WSGIController.__call__(self, environ, change_content)
231 output = list(output)
235 output = list(output)
232 headers.append(('Content-Length', str(len(output[0]))))
236 headers.append(('Content-Length', str(len(output[0]))))
233 replace_header(headers, 'Content-Type', 'application/json')
237 replace_header(headers, 'Content-Type', 'application/json')
234 start_response(status[0], headers, exc_info[0])
238 start_response(status[0], headers, exc_info[0])
235 log.info('IP: %s Request to %s time: %.3fs' % (
239 log.info('IP: %s Request to %s time: %.3fs' % (
236 _get_ip_addr(environ),
240 _get_ip_addr(environ),
237 safe_unicode(_get_access_path(environ)), time.time() - start)
241 safe_unicode(_get_access_path(environ)), time.time() - start)
238 )
242 )
239 return output
243 return output
240
244
241 def _dispatch_call(self):
245 def _dispatch_call(self):
242 """
246 """
243 Implement dispatch interface specified by WSGIController
247 Implement dispatch interface specified by WSGIController
244 """
248 """
245 try:
249 try:
246 raw_response = self._inspect_call(self._func)
250 raw_response = self._inspect_call(self._func)
247 if isinstance(raw_response, HTTPError):
251 if isinstance(raw_response, HTTPError):
248 self._error = str(raw_response)
252 self._error = str(raw_response)
249 except JSONRPCError, e:
253 except JSONRPCError, e:
250 self._error = str(e)
254 self._error = str(e)
251 except Exception, e:
255 except Exception, e:
252 log.error('Encountered unhandled exception: %s' \
256 log.error('Encountered unhandled exception: %s' \
253 % traceback.format_exc())
257 % traceback.format_exc())
254 json_exc = JSONRPCError('Internal server error')
258 json_exc = JSONRPCError('Internal server error')
255 self._error = str(json_exc)
259 self._error = str(json_exc)
256
260
257 if self._error is not None:
261 if self._error is not None:
258 raw_response = None
262 raw_response = None
259
263
260 response = dict(id=self._req_id, result=raw_response,
264 response = dict(id=self._req_id, result=raw_response,
261 error=self._error)
265 error=self._error)
262
266
263 try:
267 try:
264 return json.dumps(response)
268 return json.dumps(response)
265 except TypeError, e:
269 except TypeError, e:
266 log.error('API FAILED. Error encoding response: %s' % e)
270 log.error('API FAILED. Error encoding response: %s' % e)
267 return json.dumps(
271 return json.dumps(
268 dict(
272 dict(
269 id=self._req_id,
273 id=self._req_id,
270 result=None,
274 result=None,
271 error="Error encoding response"
275 error="Error encoding response"
272 )
276 )
273 )
277 )
274
278
275 def _find_method(self):
279 def _find_method(self):
276 """
280 """
277 Return method named by `self._req_method` in controller if able
281 Return method named by `self._req_method` in controller if able
278 """
282 """
279 log.debug('Trying to find JSON-RPC method: %s' % self._req_method)
283 log.debug('Trying to find JSON-RPC method: %s' % self._req_method)
280 if self._req_method.startswith('_'):
284 if self._req_method.startswith('_'):
281 raise AttributeError("Method not allowed")
285 raise AttributeError("Method not allowed")
282
286
283 try:
287 try:
284 func = getattr(self, self._req_method, None)
288 func = getattr(self, self._req_method, None)
285 except UnicodeEncodeError:
289 except UnicodeEncodeError:
286 raise AttributeError("Problem decoding unicode in requested "
290 raise AttributeError("Problem decoding unicode in requested "
287 "method name.")
291 "method name.")
288
292
289 if isinstance(func, types.MethodType):
293 if isinstance(func, types.MethodType):
290 return func
294 return func
291 else:
295 else:
292 raise AttributeError("No such method: %s" % self._req_method)
296 raise AttributeError("No such method: %s" % self._req_method)
@@ -1,1237 +1,1265 b''
1 from __future__ import with_statement
1 from __future__ import with_statement
2 import random
2 import random
3 import mock
3 import mock
4
4
5 from rhodecode.tests import *
5 from rhodecode.tests import *
6 from rhodecode.lib.compat import json
6 from rhodecode.lib.compat import json
7 from rhodecode.lib.auth import AuthUser
7 from rhodecode.lib.auth import AuthUser
8 from rhodecode.model.user import UserModel
8 from rhodecode.model.user import UserModel
9 from rhodecode.model.users_group import UsersGroupModel
9 from rhodecode.model.users_group import UsersGroupModel
10 from rhodecode.model.repo import RepoModel
10 from rhodecode.model.repo import RepoModel
11 from rhodecode.model.meta import Session
11 from rhodecode.model.meta import Session
12 from rhodecode.model.scm import ScmModel
12 from rhodecode.model.scm import ScmModel
13 from rhodecode.model.db import Repository
13 from rhodecode.model.db import Repository
14
14
15 API_URL = '/_admin/api'
15 API_URL = '/_admin/api'
16
16
17
17
18 def _build_data(apikey, method, **kw):
18 def _build_data(apikey, method, **kw):
19 """
19 """
20 Builds API data with given random ID
20 Builds API data with given random ID
21
21
22 :param random_id:
22 :param random_id:
23 :type random_id:
23 :type random_id:
24 """
24 """
25 random_id = random.randrange(1, 9999)
25 random_id = random.randrange(1, 9999)
26 return random_id, json.dumps({
26 return random_id, json.dumps({
27 "id": random_id,
27 "id": random_id,
28 "api_key": apikey,
28 "api_key": apikey,
29 "method": method,
29 "method": method,
30 "args": kw
30 "args": kw
31 })
31 })
32
32
33 jsonify = lambda obj: json.loads(json.dumps(obj))
33 jsonify = lambda obj: json.loads(json.dumps(obj))
34
34
35
35
36 def crash(*args, **kwargs):
36 def crash(*args, **kwargs):
37 raise Exception('Total Crash !')
37 raise Exception('Total Crash !')
38
38
39
39
40 def api_call(test_obj, params):
40 def api_call(test_obj, params):
41 response = test_obj.app.post(API_URL, content_type='application/json',
41 response = test_obj.app.post(API_URL, content_type='application/json',
42 params=params)
42 params=params)
43 return response
43 return response
44
44
45
45
46 TEST_USERS_GROUP = 'test_users_group'
46 TEST_USERS_GROUP = 'test_users_group'
47
47
48
48
49 def make_users_group(name=TEST_USERS_GROUP):
49 def make_users_group(name=TEST_USERS_GROUP):
50 gr = UsersGroupModel().create(name=name)
50 gr = UsersGroupModel().create(name=name)
51 UsersGroupModel().add_user_to_group(users_group=gr,
51 UsersGroupModel().add_user_to_group(users_group=gr,
52 user=TEST_USER_ADMIN_LOGIN)
52 user=TEST_USER_ADMIN_LOGIN)
53 Session().commit()
53 Session().commit()
54 return gr
54 return gr
55
55
56
56
57 def destroy_users_group(name=TEST_USERS_GROUP):
57 def destroy_users_group(name=TEST_USERS_GROUP):
58 UsersGroupModel().delete(users_group=name, force=True)
58 UsersGroupModel().delete(users_group=name, force=True)
59 Session().commit()
59 Session().commit()
60
60
61
61
62 def create_repo(repo_name, repo_type, owner=None):
62 def create_repo(repo_name, repo_type, owner=None):
63 # create new repo
63 # create new repo
64 form_data = _get_repo_create_params(
64 form_data = _get_repo_create_params(
65 repo_name_full=repo_name,
65 repo_name_full=repo_name,
66 repo_description='description %s' % repo_name,
66 repo_description='description %s' % repo_name,
67 )
67 )
68 cur_user = UserModel().get_by_username(owner or TEST_USER_ADMIN_LOGIN)
68 cur_user = UserModel().get_by_username(owner or TEST_USER_ADMIN_LOGIN)
69 r = RepoModel().create(form_data, cur_user)
69 r = RepoModel().create(form_data, cur_user)
70 Session().commit()
70 Session().commit()
71 return r
71 return r
72
72
73
73
74 def create_fork(fork_name, fork_type, fork_of):
74 def create_fork(fork_name, fork_type, fork_of):
75 fork = RepoModel(Session())._get_repo(fork_of)
75 fork = RepoModel(Session())._get_repo(fork_of)
76 r = create_repo(fork_name, fork_type)
76 r = create_repo(fork_name, fork_type)
77 r.fork = fork
77 r.fork = fork
78 Session().add(r)
78 Session().add(r)
79 Session().commit()
79 Session().commit()
80 return r
80 return r
81
81
82
82
83 def destroy_repo(repo_name):
83 def destroy_repo(repo_name):
84 RepoModel().delete(repo_name)
84 RepoModel().delete(repo_name)
85 Session().commit()
85 Session().commit()
86
86
87
87
88 class BaseTestApi(object):
88 class BaseTestApi(object):
89 REPO = None
89 REPO = None
90 REPO_TYPE = None
90 REPO_TYPE = None
91
91
92 @classmethod
92 @classmethod
93 def setUpClass(self):
93 def setUpClass(self):
94 self.usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
94 self.usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
95 self.apikey = self.usr.api_key
95 self.apikey = self.usr.api_key
96 self.test_user = UserModel().create_or_update(
96 self.test_user = UserModel().create_or_update(
97 username='test-api',
97 username='test-api',
98 password='test',
98 password='test',
99 email='test@api.rhodecode.org',
99 email='test@api.rhodecode.org',
100 firstname='first',
100 firstname='first',
101 lastname='last'
101 lastname='last'
102 )
102 )
103 Session().commit()
103 Session().commit()
104 self.TEST_USER_LOGIN = self.test_user.username
104 self.TEST_USER_LOGIN = self.test_user.username
105 self.apikey_regular = self.test_user.api_key
105 self.apikey_regular = self.test_user.api_key
106
106
107 @classmethod
107 @classmethod
108 def teardownClass(self):
108 def teardownClass(self):
109 pass
109 pass
110
110
111 def setUp(self):
111 def setUp(self):
112 self.maxDiff = None
112 self.maxDiff = None
113 make_users_group()
113 make_users_group()
114
114
115 def tearDown(self):
115 def tearDown(self):
116 destroy_users_group()
116 destroy_users_group()
117
117
118 def _compare_ok(self, id_, expected, given):
118 def _compare_ok(self, id_, expected, given):
119 expected = jsonify({
119 expected = jsonify({
120 'id': id_,
120 'id': id_,
121 'error': None,
121 'error': None,
122 'result': expected
122 'result': expected
123 })
123 })
124 given = json.loads(given)
124 given = json.loads(given)
125 self.assertEqual(expected, given)
125 self.assertEqual(expected, given)
126
126
127 def _compare_error(self, id_, expected, given):
127 def _compare_error(self, id_, expected, given):
128 expected = jsonify({
128 expected = jsonify({
129 'id': id_,
129 'id': id_,
130 'error': expected,
130 'error': expected,
131 'result': None
131 'result': None
132 })
132 })
133 given = json.loads(given)
133 given = json.loads(given)
134 self.assertEqual(expected, given)
134 self.assertEqual(expected, given)
135
135
136 # def test_Optional(self):
136 # def test_Optional(self):
137 # from rhodecode.controllers.api.api import Optional
137 # from rhodecode.controllers.api.api import Optional
138 # option1 = Optional(None)
138 # option1 = Optional(None)
139 # self.assertEqual('<Optional:%s>' % None, repr(option1))
139 # self.assertEqual('<Optional:%s>' % None, repr(option1))
140 #
140 #
141 # self.assertEqual(1, Optional.extract(Optional(1)))
141 # self.assertEqual(1, Optional.extract(Optional(1)))
142 # self.assertEqual('trololo', Optional.extract('trololo'))
142 # self.assertEqual('trololo', Optional.extract('trololo'))
143
143
144 def test_api_wrong_key(self):
144 def test_api_wrong_key(self):
145 id_, params = _build_data('trololo', 'get_user')
145 id_, params = _build_data('trololo', 'get_user')
146 response = api_call(self, params)
146 response = api_call(self, params)
147
147
148 expected = 'Invalid API KEY'
148 expected = 'Invalid API KEY'
149 self._compare_error(id_, expected, given=response.body)
149 self._compare_error(id_, expected, given=response.body)
150
150
151 def test_api_missing_non_optional_param(self):
151 def test_api_missing_non_optional_param(self):
152 id_, params = _build_data(self.apikey, 'get_repo')
152 id_, params = _build_data(self.apikey, 'get_repo')
153 response = api_call(self, params)
153 response = api_call(self, params)
154
154
155 expected = 'Missing non optional `repoid` arg in JSON DATA'
155 expected = 'Missing non optional `repoid` arg in JSON DATA'
156 self._compare_error(id_, expected, given=response.body)
156 self._compare_error(id_, expected, given=response.body)
157
157
158 def test_api_missing_non_optional_param_args_null(self):
159 id_, params = _build_data(self.apikey, 'get_repo')
160 params = params.replace('"args": {}', '"args": null')
161 response = api_call(self, params)
162
163 expected = 'Missing non optional `repoid` arg in JSON DATA'
164 self._compare_error(id_, expected, given=response.body)
165
166 def test_api_missing_non_optional_param_args_bad(self):
167 id_, params = _build_data(self.apikey, 'get_repo')
168 params = params.replace('"args": {}', '"args": 1')
169 response = api_call(self, params)
170
171 expected = 'Missing non optional `repoid` arg in JSON DATA'
172 self._compare_error(id_, expected, given=response.body)
173
174 def test_api_args_is_null(self):
175 id_, params = _build_data(self.apikey, 'get_users',)
176 params = params.replace('"args": {}', '"args": null')
177 response = api_call(self, params)
178 self.assertEqual(response.status, '200 OK')
179
180 def test_api_args_is_bad(self):
181 id_, params = _build_data(self.apikey, 'get_users',)
182 params = params.replace('"args": {}', '"args": 1')
183 response = api_call(self, params)
184 self.assertEqual(response.status, '200 OK')
185
158 def test_api_get_users(self):
186 def test_api_get_users(self):
159 id_, params = _build_data(self.apikey, 'get_users',)
187 id_, params = _build_data(self.apikey, 'get_users',)
160 response = api_call(self, params)
188 response = api_call(self, params)
161 ret_all = []
189 ret_all = []
162 for usr in UserModel().get_all():
190 for usr in UserModel().get_all():
163 ret = usr.get_api_data()
191 ret = usr.get_api_data()
164 ret_all.append(jsonify(ret))
192 ret_all.append(jsonify(ret))
165 expected = ret_all
193 expected = ret_all
166 self._compare_ok(id_, expected, given=response.body)
194 self._compare_ok(id_, expected, given=response.body)
167
195
168 def test_api_get_user(self):
196 def test_api_get_user(self):
169 id_, params = _build_data(self.apikey, 'get_user',
197 id_, params = _build_data(self.apikey, 'get_user',
170 userid=TEST_USER_ADMIN_LOGIN)
198 userid=TEST_USER_ADMIN_LOGIN)
171 response = api_call(self, params)
199 response = api_call(self, params)
172
200
173 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
201 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
174 ret = usr.get_api_data()
202 ret = usr.get_api_data()
175 ret['permissions'] = AuthUser(usr.user_id).permissions
203 ret['permissions'] = AuthUser(usr.user_id).permissions
176
204
177 expected = ret
205 expected = ret
178 self._compare_ok(id_, expected, given=response.body)
206 self._compare_ok(id_, expected, given=response.body)
179
207
180 def test_api_get_user_that_does_not_exist(self):
208 def test_api_get_user_that_does_not_exist(self):
181 id_, params = _build_data(self.apikey, 'get_user',
209 id_, params = _build_data(self.apikey, 'get_user',
182 userid='trololo')
210 userid='trololo')
183 response = api_call(self, params)
211 response = api_call(self, params)
184
212
185 expected = "user `%s` does not exist" % 'trololo'
213 expected = "user `%s` does not exist" % 'trololo'
186 self._compare_error(id_, expected, given=response.body)
214 self._compare_error(id_, expected, given=response.body)
187
215
188 def test_api_get_user_without_giving_userid(self):
216 def test_api_get_user_without_giving_userid(self):
189 id_, params = _build_data(self.apikey, 'get_user')
217 id_, params = _build_data(self.apikey, 'get_user')
190 response = api_call(self, params)
218 response = api_call(self, params)
191
219
192 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
220 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
193 ret = usr.get_api_data()
221 ret = usr.get_api_data()
194 ret['permissions'] = AuthUser(usr.user_id).permissions
222 ret['permissions'] = AuthUser(usr.user_id).permissions
195
223
196 expected = ret
224 expected = ret
197 self._compare_ok(id_, expected, given=response.body)
225 self._compare_ok(id_, expected, given=response.body)
198
226
199 def test_api_get_user_without_giving_userid_non_admin(self):
227 def test_api_get_user_without_giving_userid_non_admin(self):
200 id_, params = _build_data(self.apikey_regular, 'get_user')
228 id_, params = _build_data(self.apikey_regular, 'get_user')
201 response = api_call(self, params)
229 response = api_call(self, params)
202
230
203 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
231 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
204 ret = usr.get_api_data()
232 ret = usr.get_api_data()
205 ret['permissions'] = AuthUser(usr.user_id).permissions
233 ret['permissions'] = AuthUser(usr.user_id).permissions
206
234
207 expected = ret
235 expected = ret
208 self._compare_ok(id_, expected, given=response.body)
236 self._compare_ok(id_, expected, given=response.body)
209
237
210 def test_api_get_user_with_giving_userid_non_admin(self):
238 def test_api_get_user_with_giving_userid_non_admin(self):
211 id_, params = _build_data(self.apikey_regular, 'get_user',
239 id_, params = _build_data(self.apikey_regular, 'get_user',
212 userid=self.TEST_USER_LOGIN)
240 userid=self.TEST_USER_LOGIN)
213 response = api_call(self, params)
241 response = api_call(self, params)
214
242
215 expected = 'userid is not the same as your user'
243 expected = 'userid is not the same as your user'
216 self._compare_error(id_, expected, given=response.body)
244 self._compare_error(id_, expected, given=response.body)
217
245
218 def test_api_pull(self):
246 def test_api_pull(self):
219 #TODO: issues with rhodecode_extras here.. not sure why !
247 #TODO: issues with rhodecode_extras here.. not sure why !
220 pass
248 pass
221
249
222 # repo_name = 'test_pull'
250 # repo_name = 'test_pull'
223 # r = create_repo(repo_name, self.REPO_TYPE)
251 # r = create_repo(repo_name, self.REPO_TYPE)
224 # r.clone_uri = TEST_self.REPO
252 # r.clone_uri = TEST_self.REPO
225 # Session.add(r)
253 # Session.add(r)
226 # Session.commit()
254 # Session.commit()
227 #
255 #
228 # id_, params = _build_data(self.apikey, 'pull',
256 # id_, params = _build_data(self.apikey, 'pull',
229 # repoid=repo_name,)
257 # repoid=repo_name,)
230 # response = self.app.post(API_URL, content_type='application/json',
258 # response = self.app.post(API_URL, content_type='application/json',
231 # params=params)
259 # params=params)
232 #
260 #
233 # expected = 'Pulled from `%s`' % repo_name
261 # expected = 'Pulled from `%s`' % repo_name
234 # self._compare_ok(id_, expected, given=response.body)
262 # self._compare_ok(id_, expected, given=response.body)
235 #
263 #
236 # destroy_repo(repo_name)
264 # destroy_repo(repo_name)
237
265
238 def test_api_pull_error(self):
266 def test_api_pull_error(self):
239 id_, params = _build_data(self.apikey, 'pull',
267 id_, params = _build_data(self.apikey, 'pull',
240 repoid=self.REPO,)
268 repoid=self.REPO,)
241 response = api_call(self, params)
269 response = api_call(self, params)
242
270
243 expected = 'Unable to pull changes from `%s`' % self.REPO
271 expected = 'Unable to pull changes from `%s`' % self.REPO
244 self._compare_error(id_, expected, given=response.body)
272 self._compare_error(id_, expected, given=response.body)
245
273
246 def test_api_rescan_repos(self):
274 def test_api_rescan_repos(self):
247 id_, params = _build_data(self.apikey, 'rescan_repos')
275 id_, params = _build_data(self.apikey, 'rescan_repos')
248 response = api_call(self, params)
276 response = api_call(self, params)
249
277
250 expected = {'added': [], 'removed': []}
278 expected = {'added': [], 'removed': []}
251 self._compare_ok(id_, expected, given=response.body)
279 self._compare_ok(id_, expected, given=response.body)
252
280
253 @mock.patch.object(ScmModel, 'repo_scan', crash)
281 @mock.patch.object(ScmModel, 'repo_scan', crash)
254 def test_api_rescann_error(self):
282 def test_api_rescann_error(self):
255 id_, params = _build_data(self.apikey, 'rescan_repos',)
283 id_, params = _build_data(self.apikey, 'rescan_repos',)
256 response = api_call(self, params)
284 response = api_call(self, params)
257
285
258 expected = 'Error occurred during rescan repositories action'
286 expected = 'Error occurred during rescan repositories action'
259 self._compare_error(id_, expected, given=response.body)
287 self._compare_error(id_, expected, given=response.body)
260
288
261 def test_api_lock_repo_lock_aquire(self):
289 def test_api_lock_repo_lock_aquire(self):
262 id_, params = _build_data(self.apikey, 'lock',
290 id_, params = _build_data(self.apikey, 'lock',
263 userid=TEST_USER_ADMIN_LOGIN,
291 userid=TEST_USER_ADMIN_LOGIN,
264 repoid=self.REPO,
292 repoid=self.REPO,
265 locked=True)
293 locked=True)
266 response = api_call(self, params)
294 response = api_call(self, params)
267 expected = ('User `%s` set lock state for repo `%s` to `%s`'
295 expected = ('User `%s` set lock state for repo `%s` to `%s`'
268 % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
296 % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
269 self._compare_ok(id_, expected, given=response.body)
297 self._compare_ok(id_, expected, given=response.body)
270
298
271 def test_api_lock_repo_lock_aquire_by_non_admin(self):
299 def test_api_lock_repo_lock_aquire_by_non_admin(self):
272 repo_name = 'api_delete_me'
300 repo_name = 'api_delete_me'
273 create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
301 create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
274 try:
302 try:
275 id_, params = _build_data(self.apikey_regular, 'lock',
303 id_, params = _build_data(self.apikey_regular, 'lock',
276 repoid=repo_name,
304 repoid=repo_name,
277 locked=True)
305 locked=True)
278 response = api_call(self, params)
306 response = api_call(self, params)
279 expected = ('User `%s` set lock state for repo `%s` to `%s`'
307 expected = ('User `%s` set lock state for repo `%s` to `%s`'
280 % (self.TEST_USER_LOGIN, repo_name, True))
308 % (self.TEST_USER_LOGIN, repo_name, True))
281 self._compare_ok(id_, expected, given=response.body)
309 self._compare_ok(id_, expected, given=response.body)
282 finally:
310 finally:
283 destroy_repo(repo_name)
311 destroy_repo(repo_name)
284
312
285 def test_api_lock_repo_lock_aquire_non_admin_with_userid(self):
313 def test_api_lock_repo_lock_aquire_non_admin_with_userid(self):
286 repo_name = 'api_delete_me'
314 repo_name = 'api_delete_me'
287 create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
315 create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
288 try:
316 try:
289 id_, params = _build_data(self.apikey_regular, 'lock',
317 id_, params = _build_data(self.apikey_regular, 'lock',
290 userid=TEST_USER_ADMIN_LOGIN,
318 userid=TEST_USER_ADMIN_LOGIN,
291 repoid=repo_name,
319 repoid=repo_name,
292 locked=True)
320 locked=True)
293 response = api_call(self, params)
321 response = api_call(self, params)
294 expected = 'userid is not the same as your user'
322 expected = 'userid is not the same as your user'
295 self._compare_error(id_, expected, given=response.body)
323 self._compare_error(id_, expected, given=response.body)
296 finally:
324 finally:
297 destroy_repo(repo_name)
325 destroy_repo(repo_name)
298
326
299 def test_api_lock_repo_lock_aquire_non_admin_not_his_repo(self):
327 def test_api_lock_repo_lock_aquire_non_admin_not_his_repo(self):
300 id_, params = _build_data(self.apikey_regular, 'lock',
328 id_, params = _build_data(self.apikey_regular, 'lock',
301 repoid=self.REPO,
329 repoid=self.REPO,
302 locked=True)
330 locked=True)
303 response = api_call(self, params)
331 response = api_call(self, params)
304 expected = 'repository `%s` does not exist' % (self.REPO)
332 expected = 'repository `%s` does not exist' % (self.REPO)
305 self._compare_error(id_, expected, given=response.body)
333 self._compare_error(id_, expected, given=response.body)
306
334
307 def test_api_lock_repo_lock_release(self):
335 def test_api_lock_repo_lock_release(self):
308 id_, params = _build_data(self.apikey, 'lock',
336 id_, params = _build_data(self.apikey, 'lock',
309 userid=TEST_USER_ADMIN_LOGIN,
337 userid=TEST_USER_ADMIN_LOGIN,
310 repoid=self.REPO,
338 repoid=self.REPO,
311 locked=False)
339 locked=False)
312 response = api_call(self, params)
340 response = api_call(self, params)
313 expected = ('User `%s` set lock state for repo `%s` to `%s`'
341 expected = ('User `%s` set lock state for repo `%s` to `%s`'
314 % (TEST_USER_ADMIN_LOGIN, self.REPO, False))
342 % (TEST_USER_ADMIN_LOGIN, self.REPO, False))
315 self._compare_ok(id_, expected, given=response.body)
343 self._compare_ok(id_, expected, given=response.body)
316
344
317 def test_api_lock_repo_lock_aquire_optional_userid(self):
345 def test_api_lock_repo_lock_aquire_optional_userid(self):
318 id_, params = _build_data(self.apikey, 'lock',
346 id_, params = _build_data(self.apikey, 'lock',
319 repoid=self.REPO,
347 repoid=self.REPO,
320 locked=True)
348 locked=True)
321 response = api_call(self, params)
349 response = api_call(self, params)
322 expected = ('User `%s` set lock state for repo `%s` to `%s`'
350 expected = ('User `%s` set lock state for repo `%s` to `%s`'
323 % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
351 % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
324 self._compare_ok(id_, expected, given=response.body)
352 self._compare_ok(id_, expected, given=response.body)
325
353
326 @mock.patch.object(Repository, 'lock', crash)
354 @mock.patch.object(Repository, 'lock', crash)
327 def test_api_lock_error(self):
355 def test_api_lock_error(self):
328 id_, params = _build_data(self.apikey, 'lock',
356 id_, params = _build_data(self.apikey, 'lock',
329 userid=TEST_USER_ADMIN_LOGIN,
357 userid=TEST_USER_ADMIN_LOGIN,
330 repoid=self.REPO,
358 repoid=self.REPO,
331 locked=True)
359 locked=True)
332 response = api_call(self, params)
360 response = api_call(self, params)
333
361
334 expected = 'Error occurred locking repository `%s`' % self.REPO
362 expected = 'Error occurred locking repository `%s`' % self.REPO
335 self._compare_error(id_, expected, given=response.body)
363 self._compare_error(id_, expected, given=response.body)
336
364
337 def test_api_create_existing_user(self):
365 def test_api_create_existing_user(self):
338 id_, params = _build_data(self.apikey, 'create_user',
366 id_, params = _build_data(self.apikey, 'create_user',
339 username=TEST_USER_ADMIN_LOGIN,
367 username=TEST_USER_ADMIN_LOGIN,
340 email='test@foo.com',
368 email='test@foo.com',
341 password='trololo')
369 password='trololo')
342 response = api_call(self, params)
370 response = api_call(self, params)
343
371
344 expected = "user `%s` already exist" % TEST_USER_ADMIN_LOGIN
372 expected = "user `%s` already exist" % TEST_USER_ADMIN_LOGIN
345 self._compare_error(id_, expected, given=response.body)
373 self._compare_error(id_, expected, given=response.body)
346
374
347 def test_api_create_user_with_existing_email(self):
375 def test_api_create_user_with_existing_email(self):
348 id_, params = _build_data(self.apikey, 'create_user',
376 id_, params = _build_data(self.apikey, 'create_user',
349 username=TEST_USER_ADMIN_LOGIN + 'new',
377 username=TEST_USER_ADMIN_LOGIN + 'new',
350 email=TEST_USER_REGULAR_EMAIL,
378 email=TEST_USER_REGULAR_EMAIL,
351 password='trololo')
379 password='trololo')
352 response = api_call(self, params)
380 response = api_call(self, params)
353
381
354 expected = "email `%s` already exist" % TEST_USER_REGULAR_EMAIL
382 expected = "email `%s` already exist" % TEST_USER_REGULAR_EMAIL
355 self._compare_error(id_, expected, given=response.body)
383 self._compare_error(id_, expected, given=response.body)
356
384
357 def test_api_create_user(self):
385 def test_api_create_user(self):
358 username = 'test_new_api_user'
386 username = 'test_new_api_user'
359 email = username + "@foo.com"
387 email = username + "@foo.com"
360
388
361 id_, params = _build_data(self.apikey, 'create_user',
389 id_, params = _build_data(self.apikey, 'create_user',
362 username=username,
390 username=username,
363 email=email,
391 email=email,
364 password='trololo')
392 password='trololo')
365 response = api_call(self, params)
393 response = api_call(self, params)
366
394
367 usr = UserModel().get_by_username(username)
395 usr = UserModel().get_by_username(username)
368 ret = dict(
396 ret = dict(
369 msg='created new user `%s`' % username,
397 msg='created new user `%s`' % username,
370 user=jsonify(usr.get_api_data())
398 user=jsonify(usr.get_api_data())
371 )
399 )
372
400
373 expected = ret
401 expected = ret
374 self._compare_ok(id_, expected, given=response.body)
402 self._compare_ok(id_, expected, given=response.body)
375
403
376 UserModel().delete(usr.user_id)
404 UserModel().delete(usr.user_id)
377 Session().commit()
405 Session().commit()
378
406
379 @mock.patch.object(UserModel, 'create_or_update', crash)
407 @mock.patch.object(UserModel, 'create_or_update', crash)
380 def test_api_create_user_when_exception_happened(self):
408 def test_api_create_user_when_exception_happened(self):
381
409
382 username = 'test_new_api_user'
410 username = 'test_new_api_user'
383 email = username + "@foo.com"
411 email = username + "@foo.com"
384
412
385 id_, params = _build_data(self.apikey, 'create_user',
413 id_, params = _build_data(self.apikey, 'create_user',
386 username=username,
414 username=username,
387 email=email,
415 email=email,
388 password='trololo')
416 password='trololo')
389 response = api_call(self, params)
417 response = api_call(self, params)
390 expected = 'failed to create user `%s`' % username
418 expected = 'failed to create user `%s`' % username
391 self._compare_error(id_, expected, given=response.body)
419 self._compare_error(id_, expected, given=response.body)
392
420
393 def test_api_delete_user(self):
421 def test_api_delete_user(self):
394 usr = UserModel().create_or_update(username=u'test_user',
422 usr = UserModel().create_or_update(username=u'test_user',
395 password=u'qweqwe',
423 password=u'qweqwe',
396 email=u'u232@rhodecode.org',
424 email=u'u232@rhodecode.org',
397 firstname=u'u1', lastname=u'u1')
425 firstname=u'u1', lastname=u'u1')
398 Session().commit()
426 Session().commit()
399 username = usr.username
427 username = usr.username
400 email = usr.email
428 email = usr.email
401 usr_id = usr.user_id
429 usr_id = usr.user_id
402 ## DELETE THIS USER NOW
430 ## DELETE THIS USER NOW
403
431
404 id_, params = _build_data(self.apikey, 'delete_user',
432 id_, params = _build_data(self.apikey, 'delete_user',
405 userid=username,)
433 userid=username,)
406 response = api_call(self, params)
434 response = api_call(self, params)
407
435
408 ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username),
436 ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username),
409 'user': None}
437 'user': None}
410 expected = ret
438 expected = ret
411 self._compare_ok(id_, expected, given=response.body)
439 self._compare_ok(id_, expected, given=response.body)
412
440
413 @mock.patch.object(UserModel, 'delete', crash)
441 @mock.patch.object(UserModel, 'delete', crash)
414 def test_api_delete_user_when_exception_happened(self):
442 def test_api_delete_user_when_exception_happened(self):
415 usr = UserModel().create_or_update(username=u'test_user',
443 usr = UserModel().create_or_update(username=u'test_user',
416 password=u'qweqwe',
444 password=u'qweqwe',
417 email=u'u232@rhodecode.org',
445 email=u'u232@rhodecode.org',
418 firstname=u'u1', lastname=u'u1')
446 firstname=u'u1', lastname=u'u1')
419 Session().commit()
447 Session().commit()
420 username = usr.username
448 username = usr.username
421
449
422 id_, params = _build_data(self.apikey, 'delete_user',
450 id_, params = _build_data(self.apikey, 'delete_user',
423 userid=username,)
451 userid=username,)
424 response = api_call(self, params)
452 response = api_call(self, params)
425 ret = 'failed to delete ID:%s %s' % (usr.user_id,
453 ret = 'failed to delete ID:%s %s' % (usr.user_id,
426 usr.username)
454 usr.username)
427 expected = ret
455 expected = ret
428 self._compare_error(id_, expected, given=response.body)
456 self._compare_error(id_, expected, given=response.body)
429
457
430 @parameterized.expand([('firstname', 'new_username'),
458 @parameterized.expand([('firstname', 'new_username'),
431 ('lastname', 'new_username'),
459 ('lastname', 'new_username'),
432 ('email', 'new_username'),
460 ('email', 'new_username'),
433 ('admin', True),
461 ('admin', True),
434 ('admin', False),
462 ('admin', False),
435 ('ldap_dn', 'test'),
463 ('ldap_dn', 'test'),
436 ('ldap_dn', None),
464 ('ldap_dn', None),
437 ('active', False),
465 ('active', False),
438 ('active', True),
466 ('active', True),
439 ('password', 'newpass')
467 ('password', 'newpass')
440 ])
468 ])
441 def test_api_update_user(self, name, expected):
469 def test_api_update_user(self, name, expected):
442 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
470 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
443 kw = {name: expected,
471 kw = {name: expected,
444 'userid': usr.user_id}
472 'userid': usr.user_id}
445 id_, params = _build_data(self.apikey, 'update_user', **kw)
473 id_, params = _build_data(self.apikey, 'update_user', **kw)
446 response = api_call(self, params)
474 response = api_call(self, params)
447
475
448 ret = {
476 ret = {
449 'msg': 'updated user ID:%s %s' % (usr.user_id, self.TEST_USER_LOGIN),
477 'msg': 'updated user ID:%s %s' % (usr.user_id, self.TEST_USER_LOGIN),
450 'user': jsonify(UserModel()\
478 'user': jsonify(UserModel()\
451 .get_by_username(self.TEST_USER_LOGIN)\
479 .get_by_username(self.TEST_USER_LOGIN)\
452 .get_api_data())
480 .get_api_data())
453 }
481 }
454
482
455 expected = ret
483 expected = ret
456 self._compare_ok(id_, expected, given=response.body)
484 self._compare_ok(id_, expected, given=response.body)
457
485
458 def test_api_update_user_no_changed_params(self):
486 def test_api_update_user_no_changed_params(self):
459 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
487 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
460 ret = jsonify(usr.get_api_data())
488 ret = jsonify(usr.get_api_data())
461 id_, params = _build_data(self.apikey, 'update_user',
489 id_, params = _build_data(self.apikey, 'update_user',
462 userid=TEST_USER_ADMIN_LOGIN)
490 userid=TEST_USER_ADMIN_LOGIN)
463
491
464 response = api_call(self, params)
492 response = api_call(self, params)
465 ret = {
493 ret = {
466 'msg': 'updated user ID:%s %s' % (usr.user_id, TEST_USER_ADMIN_LOGIN),
494 'msg': 'updated user ID:%s %s' % (usr.user_id, TEST_USER_ADMIN_LOGIN),
467 'user': ret
495 'user': ret
468 }
496 }
469 expected = ret
497 expected = ret
470 self._compare_ok(id_, expected, given=response.body)
498 self._compare_ok(id_, expected, given=response.body)
471
499
472 def test_api_update_user_by_user_id(self):
500 def test_api_update_user_by_user_id(self):
473 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
501 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
474 ret = jsonify(usr.get_api_data())
502 ret = jsonify(usr.get_api_data())
475 id_, params = _build_data(self.apikey, 'update_user',
503 id_, params = _build_data(self.apikey, 'update_user',
476 userid=usr.user_id)
504 userid=usr.user_id)
477
505
478 response = api_call(self, params)
506 response = api_call(self, params)
479 ret = {
507 ret = {
480 'msg': 'updated user ID:%s %s' % (usr.user_id, TEST_USER_ADMIN_LOGIN),
508 'msg': 'updated user ID:%s %s' % (usr.user_id, TEST_USER_ADMIN_LOGIN),
481 'user': ret
509 'user': ret
482 }
510 }
483 expected = ret
511 expected = ret
484 self._compare_ok(id_, expected, given=response.body)
512 self._compare_ok(id_, expected, given=response.body)
485
513
486 @mock.patch.object(UserModel, 'update_user', crash)
514 @mock.patch.object(UserModel, 'update_user', crash)
487 def test_api_update_user_when_exception_happens(self):
515 def test_api_update_user_when_exception_happens(self):
488 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
516 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
489 ret = jsonify(usr.get_api_data())
517 ret = jsonify(usr.get_api_data())
490 id_, params = _build_data(self.apikey, 'update_user',
518 id_, params = _build_data(self.apikey, 'update_user',
491 userid=usr.user_id)
519 userid=usr.user_id)
492
520
493 response = api_call(self, params)
521 response = api_call(self, params)
494 ret = 'failed to update user `%s`' % usr.user_id
522 ret = 'failed to update user `%s`' % usr.user_id
495
523
496 expected = ret
524 expected = ret
497 self._compare_error(id_, expected, given=response.body)
525 self._compare_error(id_, expected, given=response.body)
498
526
499 def test_api_get_repo(self):
527 def test_api_get_repo(self):
500 new_group = 'some_new_group'
528 new_group = 'some_new_group'
501 make_users_group(new_group)
529 make_users_group(new_group)
502 RepoModel().grant_users_group_permission(repo=self.REPO,
530 RepoModel().grant_users_group_permission(repo=self.REPO,
503 group_name=new_group,
531 group_name=new_group,
504 perm='repository.read')
532 perm='repository.read')
505 Session().commit()
533 Session().commit()
506 id_, params = _build_data(self.apikey, 'get_repo',
534 id_, params = _build_data(self.apikey, 'get_repo',
507 repoid=self.REPO)
535 repoid=self.REPO)
508 response = api_call(self, params)
536 response = api_call(self, params)
509
537
510 repo = RepoModel().get_by_repo_name(self.REPO)
538 repo = RepoModel().get_by_repo_name(self.REPO)
511 ret = repo.get_api_data()
539 ret = repo.get_api_data()
512
540
513 members = []
541 members = []
514 for user in repo.repo_to_perm:
542 for user in repo.repo_to_perm:
515 perm = user.permission.permission_name
543 perm = user.permission.permission_name
516 user = user.user
544 user = user.user
517 user_data = user.get_api_data()
545 user_data = user.get_api_data()
518 user_data['type'] = "user"
546 user_data['type'] = "user"
519 user_data['permission'] = perm
547 user_data['permission'] = perm
520 members.append(user_data)
548 members.append(user_data)
521
549
522 for users_group in repo.users_group_to_perm:
550 for users_group in repo.users_group_to_perm:
523 perm = users_group.permission.permission_name
551 perm = users_group.permission.permission_name
524 users_group = users_group.users_group
552 users_group = users_group.users_group
525 users_group_data = users_group.get_api_data()
553 users_group_data = users_group.get_api_data()
526 users_group_data['type'] = "users_group"
554 users_group_data['type'] = "users_group"
527 users_group_data['permission'] = perm
555 users_group_data['permission'] = perm
528 members.append(users_group_data)
556 members.append(users_group_data)
529
557
530 ret['members'] = members
558 ret['members'] = members
531
559
532 expected = ret
560 expected = ret
533 self._compare_ok(id_, expected, given=response.body)
561 self._compare_ok(id_, expected, given=response.body)
534 destroy_users_group(new_group)
562 destroy_users_group(new_group)
535
563
536 def test_api_get_repo_by_non_admin(self):
564 def test_api_get_repo_by_non_admin(self):
537 id_, params = _build_data(self.apikey, 'get_repo',
565 id_, params = _build_data(self.apikey, 'get_repo',
538 repoid=self.REPO)
566 repoid=self.REPO)
539 response = api_call(self, params)
567 response = api_call(self, params)
540
568
541 repo = RepoModel().get_by_repo_name(self.REPO)
569 repo = RepoModel().get_by_repo_name(self.REPO)
542 ret = repo.get_api_data()
570 ret = repo.get_api_data()
543
571
544 members = []
572 members = []
545 for user in repo.repo_to_perm:
573 for user in repo.repo_to_perm:
546 perm = user.permission.permission_name
574 perm = user.permission.permission_name
547 user = user.user
575 user = user.user
548 user_data = user.get_api_data()
576 user_data = user.get_api_data()
549 user_data['type'] = "user"
577 user_data['type'] = "user"
550 user_data['permission'] = perm
578 user_data['permission'] = perm
551 members.append(user_data)
579 members.append(user_data)
552
580
553 for users_group in repo.users_group_to_perm:
581 for users_group in repo.users_group_to_perm:
554 perm = users_group.permission.permission_name
582 perm = users_group.permission.permission_name
555 users_group = users_group.users_group
583 users_group = users_group.users_group
556 users_group_data = users_group.get_api_data()
584 users_group_data = users_group.get_api_data()
557 users_group_data['type'] = "users_group"
585 users_group_data['type'] = "users_group"
558 users_group_data['permission'] = perm
586 users_group_data['permission'] = perm
559 members.append(users_group_data)
587 members.append(users_group_data)
560
588
561 ret['members'] = members
589 ret['members'] = members
562
590
563 expected = ret
591 expected = ret
564 self._compare_ok(id_, expected, given=response.body)
592 self._compare_ok(id_, expected, given=response.body)
565
593
566 def test_api_get_repo_by_non_admin_no_permission_to_repo(self):
594 def test_api_get_repo_by_non_admin_no_permission_to_repo(self):
567 RepoModel().grant_user_permission(repo=self.REPO,
595 RepoModel().grant_user_permission(repo=self.REPO,
568 user=self.TEST_USER_LOGIN,
596 user=self.TEST_USER_LOGIN,
569 perm='repository.none')
597 perm='repository.none')
570
598
571 id_, params = _build_data(self.apikey_regular, 'get_repo',
599 id_, params = _build_data(self.apikey_regular, 'get_repo',
572 repoid=self.REPO)
600 repoid=self.REPO)
573 response = api_call(self, params)
601 response = api_call(self, params)
574
602
575 expected = 'repository `%s` does not exist' % (self.REPO)
603 expected = 'repository `%s` does not exist' % (self.REPO)
576 self._compare_error(id_, expected, given=response.body)
604 self._compare_error(id_, expected, given=response.body)
577
605
578 def test_api_get_repo_that_doesn_not_exist(self):
606 def test_api_get_repo_that_doesn_not_exist(self):
579 id_, params = _build_data(self.apikey, 'get_repo',
607 id_, params = _build_data(self.apikey, 'get_repo',
580 repoid='no-such-repo')
608 repoid='no-such-repo')
581 response = api_call(self, params)
609 response = api_call(self, params)
582
610
583 ret = 'repository `%s` does not exist' % 'no-such-repo'
611 ret = 'repository `%s` does not exist' % 'no-such-repo'
584 expected = ret
612 expected = ret
585 self._compare_error(id_, expected, given=response.body)
613 self._compare_error(id_, expected, given=response.body)
586
614
587 def test_api_get_repos(self):
615 def test_api_get_repos(self):
588 id_, params = _build_data(self.apikey, 'get_repos')
616 id_, params = _build_data(self.apikey, 'get_repos')
589 response = api_call(self, params)
617 response = api_call(self, params)
590
618
591 result = []
619 result = []
592 for repo in RepoModel().get_all():
620 for repo in RepoModel().get_all():
593 result.append(repo.get_api_data())
621 result.append(repo.get_api_data())
594 ret = jsonify(result)
622 ret = jsonify(result)
595
623
596 expected = ret
624 expected = ret
597 self._compare_ok(id_, expected, given=response.body)
625 self._compare_ok(id_, expected, given=response.body)
598
626
599 def test_api_get_repos_non_admin(self):
627 def test_api_get_repos_non_admin(self):
600 id_, params = _build_data(self.apikey_regular, 'get_repos')
628 id_, params = _build_data(self.apikey_regular, 'get_repos')
601 response = api_call(self, params)
629 response = api_call(self, params)
602
630
603 result = []
631 result = []
604 for repo in RepoModel().get_all_user_repos(self.TEST_USER_LOGIN):
632 for repo in RepoModel().get_all_user_repos(self.TEST_USER_LOGIN):
605 result.append(repo.get_api_data())
633 result.append(repo.get_api_data())
606 ret = jsonify(result)
634 ret = jsonify(result)
607
635
608 expected = ret
636 expected = ret
609 self._compare_ok(id_, expected, given=response.body)
637 self._compare_ok(id_, expected, given=response.body)
610
638
611 @parameterized.expand([('all', 'all'),
639 @parameterized.expand([('all', 'all'),
612 ('dirs', 'dirs'),
640 ('dirs', 'dirs'),
613 ('files', 'files'), ])
641 ('files', 'files'), ])
614 def test_api_get_repo_nodes(self, name, ret_type):
642 def test_api_get_repo_nodes(self, name, ret_type):
615 rev = 'tip'
643 rev = 'tip'
616 path = '/'
644 path = '/'
617 id_, params = _build_data(self.apikey, 'get_repo_nodes',
645 id_, params = _build_data(self.apikey, 'get_repo_nodes',
618 repoid=self.REPO, revision=rev,
646 repoid=self.REPO, revision=rev,
619 root_path=path,
647 root_path=path,
620 ret_type=ret_type)
648 ret_type=ret_type)
621 response = api_call(self, params)
649 response = api_call(self, params)
622
650
623 # we don't the actual return types here since it's tested somewhere
651 # we don't the actual return types here since it's tested somewhere
624 # else
652 # else
625 expected = json.loads(response.body)['result']
653 expected = json.loads(response.body)['result']
626 self._compare_ok(id_, expected, given=response.body)
654 self._compare_ok(id_, expected, given=response.body)
627
655
628 def test_api_get_repo_nodes_bad_revisions(self):
656 def test_api_get_repo_nodes_bad_revisions(self):
629 rev = 'i-dont-exist'
657 rev = 'i-dont-exist'
630 path = '/'
658 path = '/'
631 id_, params = _build_data(self.apikey, 'get_repo_nodes',
659 id_, params = _build_data(self.apikey, 'get_repo_nodes',
632 repoid=self.REPO, revision=rev,
660 repoid=self.REPO, revision=rev,
633 root_path=path,)
661 root_path=path,)
634 response = api_call(self, params)
662 response = api_call(self, params)
635
663
636 expected = 'failed to get repo: `%s` nodes' % self.REPO
664 expected = 'failed to get repo: `%s` nodes' % self.REPO
637 self._compare_error(id_, expected, given=response.body)
665 self._compare_error(id_, expected, given=response.body)
638
666
639 def test_api_get_repo_nodes_bad_path(self):
667 def test_api_get_repo_nodes_bad_path(self):
640 rev = 'tip'
668 rev = 'tip'
641 path = '/idontexits'
669 path = '/idontexits'
642 id_, params = _build_data(self.apikey, 'get_repo_nodes',
670 id_, params = _build_data(self.apikey, 'get_repo_nodes',
643 repoid=self.REPO, revision=rev,
671 repoid=self.REPO, revision=rev,
644 root_path=path,)
672 root_path=path,)
645 response = api_call(self, params)
673 response = api_call(self, params)
646
674
647 expected = 'failed to get repo: `%s` nodes' % self.REPO
675 expected = 'failed to get repo: `%s` nodes' % self.REPO
648 self._compare_error(id_, expected, given=response.body)
676 self._compare_error(id_, expected, given=response.body)
649
677
650 def test_api_get_repo_nodes_bad_ret_type(self):
678 def test_api_get_repo_nodes_bad_ret_type(self):
651 rev = 'tip'
679 rev = 'tip'
652 path = '/'
680 path = '/'
653 ret_type = 'error'
681 ret_type = 'error'
654 id_, params = _build_data(self.apikey, 'get_repo_nodes',
682 id_, params = _build_data(self.apikey, 'get_repo_nodes',
655 repoid=self.REPO, revision=rev,
683 repoid=self.REPO, revision=rev,
656 root_path=path,
684 root_path=path,
657 ret_type=ret_type)
685 ret_type=ret_type)
658 response = api_call(self, params)
686 response = api_call(self, params)
659
687
660 expected = 'ret_type must be one of %s' % (['files', 'dirs', 'all'])
688 expected = 'ret_type must be one of %s' % (['files', 'dirs', 'all'])
661 self._compare_error(id_, expected, given=response.body)
689 self._compare_error(id_, expected, given=response.body)
662
690
663 def test_api_create_repo(self):
691 def test_api_create_repo(self):
664 repo_name = 'api-repo'
692 repo_name = 'api-repo'
665 id_, params = _build_data(self.apikey, 'create_repo',
693 id_, params = _build_data(self.apikey, 'create_repo',
666 repo_name=repo_name,
694 repo_name=repo_name,
667 owner=TEST_USER_ADMIN_LOGIN,
695 owner=TEST_USER_ADMIN_LOGIN,
668 repo_type='hg',
696 repo_type='hg',
669 )
697 )
670 response = api_call(self, params)
698 response = api_call(self, params)
671
699
672 repo = RepoModel().get_by_repo_name(repo_name)
700 repo = RepoModel().get_by_repo_name(repo_name)
673 ret = {
701 ret = {
674 'msg': 'Created new repository `%s`' % repo_name,
702 'msg': 'Created new repository `%s`' % repo_name,
675 'repo': jsonify(repo.get_api_data())
703 'repo': jsonify(repo.get_api_data())
676 }
704 }
677 expected = ret
705 expected = ret
678 self._compare_ok(id_, expected, given=response.body)
706 self._compare_ok(id_, expected, given=response.body)
679 destroy_repo(repo_name)
707 destroy_repo(repo_name)
680
708
681 def test_api_create_repo_unknown_owner(self):
709 def test_api_create_repo_unknown_owner(self):
682 repo_name = 'api-repo'
710 repo_name = 'api-repo'
683 owner = 'i-dont-exist'
711 owner = 'i-dont-exist'
684 id_, params = _build_data(self.apikey, 'create_repo',
712 id_, params = _build_data(self.apikey, 'create_repo',
685 repo_name=repo_name,
713 repo_name=repo_name,
686 owner=owner,
714 owner=owner,
687 repo_type='hg',
715 repo_type='hg',
688 )
716 )
689 response = api_call(self, params)
717 response = api_call(self, params)
690 expected = 'user `%s` does not exist' % owner
718 expected = 'user `%s` does not exist' % owner
691 self._compare_error(id_, expected, given=response.body)
719 self._compare_error(id_, expected, given=response.body)
692
720
693 def test_api_create_repo_dont_specify_owner(self):
721 def test_api_create_repo_dont_specify_owner(self):
694 repo_name = 'api-repo'
722 repo_name = 'api-repo'
695 owner = 'i-dont-exist'
723 owner = 'i-dont-exist'
696 id_, params = _build_data(self.apikey, 'create_repo',
724 id_, params = _build_data(self.apikey, 'create_repo',
697 repo_name=repo_name,
725 repo_name=repo_name,
698 repo_type='hg',
726 repo_type='hg',
699 )
727 )
700 response = api_call(self, params)
728 response = api_call(self, params)
701
729
702 repo = RepoModel().get_by_repo_name(repo_name)
730 repo = RepoModel().get_by_repo_name(repo_name)
703 ret = {
731 ret = {
704 'msg': 'Created new repository `%s`' % repo_name,
732 'msg': 'Created new repository `%s`' % repo_name,
705 'repo': jsonify(repo.get_api_data())
733 'repo': jsonify(repo.get_api_data())
706 }
734 }
707 expected = ret
735 expected = ret
708 self._compare_ok(id_, expected, given=response.body)
736 self._compare_ok(id_, expected, given=response.body)
709 destroy_repo(repo_name)
737 destroy_repo(repo_name)
710
738
711 def test_api_create_repo_by_non_admin(self):
739 def test_api_create_repo_by_non_admin(self):
712 repo_name = 'api-repo'
740 repo_name = 'api-repo'
713 owner = 'i-dont-exist'
741 owner = 'i-dont-exist'
714 id_, params = _build_data(self.apikey_regular, 'create_repo',
742 id_, params = _build_data(self.apikey_regular, 'create_repo',
715 repo_name=repo_name,
743 repo_name=repo_name,
716 repo_type='hg',
744 repo_type='hg',
717 )
745 )
718 response = api_call(self, params)
746 response = api_call(self, params)
719
747
720 repo = RepoModel().get_by_repo_name(repo_name)
748 repo = RepoModel().get_by_repo_name(repo_name)
721 ret = {
749 ret = {
722 'msg': 'Created new repository `%s`' % repo_name,
750 'msg': 'Created new repository `%s`' % repo_name,
723 'repo': jsonify(repo.get_api_data())
751 'repo': jsonify(repo.get_api_data())
724 }
752 }
725 expected = ret
753 expected = ret
726 self._compare_ok(id_, expected, given=response.body)
754 self._compare_ok(id_, expected, given=response.body)
727 destroy_repo(repo_name)
755 destroy_repo(repo_name)
728
756
729 def test_api_create_repo_by_non_admin_specify_owner(self):
757 def test_api_create_repo_by_non_admin_specify_owner(self):
730 repo_name = 'api-repo'
758 repo_name = 'api-repo'
731 owner = 'i-dont-exist'
759 owner = 'i-dont-exist'
732 id_, params = _build_data(self.apikey_regular, 'create_repo',
760 id_, params = _build_data(self.apikey_regular, 'create_repo',
733 repo_name=repo_name,
761 repo_name=repo_name,
734 repo_type='hg',
762 repo_type='hg',
735 owner=owner
763 owner=owner
736 )
764 )
737 response = api_call(self, params)
765 response = api_call(self, params)
738
766
739 expected = 'Only RhodeCode admin can specify `owner` param'
767 expected = 'Only RhodeCode admin can specify `owner` param'
740 self._compare_error(id_, expected, given=response.body)
768 self._compare_error(id_, expected, given=response.body)
741 destroy_repo(repo_name)
769 destroy_repo(repo_name)
742
770
743 def test_api_create_repo_exists(self):
771 def test_api_create_repo_exists(self):
744 repo_name = self.REPO
772 repo_name = self.REPO
745 id_, params = _build_data(self.apikey, 'create_repo',
773 id_, params = _build_data(self.apikey, 'create_repo',
746 repo_name=repo_name,
774 repo_name=repo_name,
747 owner=TEST_USER_ADMIN_LOGIN,
775 owner=TEST_USER_ADMIN_LOGIN,
748 repo_type='hg',
776 repo_type='hg',
749 )
777 )
750 response = api_call(self, params)
778 response = api_call(self, params)
751 expected = "repo `%s` already exist" % repo_name
779 expected = "repo `%s` already exist" % repo_name
752 self._compare_error(id_, expected, given=response.body)
780 self._compare_error(id_, expected, given=response.body)
753
781
754 @mock.patch.object(RepoModel, 'create_repo', crash)
782 @mock.patch.object(RepoModel, 'create_repo', crash)
755 def test_api_create_repo_exception_occurred(self):
783 def test_api_create_repo_exception_occurred(self):
756 repo_name = 'api-repo'
784 repo_name = 'api-repo'
757 id_, params = _build_data(self.apikey, 'create_repo',
785 id_, params = _build_data(self.apikey, 'create_repo',
758 repo_name=repo_name,
786 repo_name=repo_name,
759 owner=TEST_USER_ADMIN_LOGIN,
787 owner=TEST_USER_ADMIN_LOGIN,
760 repo_type='hg',
788 repo_type='hg',
761 )
789 )
762 response = api_call(self, params)
790 response = api_call(self, params)
763 expected = 'failed to create repository `%s`' % repo_name
791 expected = 'failed to create repository `%s`' % repo_name
764 self._compare_error(id_, expected, given=response.body)
792 self._compare_error(id_, expected, given=response.body)
765
793
766 def test_api_delete_repo(self):
794 def test_api_delete_repo(self):
767 repo_name = 'api_delete_me'
795 repo_name = 'api_delete_me'
768 create_repo(repo_name, self.REPO_TYPE)
796 create_repo(repo_name, self.REPO_TYPE)
769
797
770 id_, params = _build_data(self.apikey, 'delete_repo',
798 id_, params = _build_data(self.apikey, 'delete_repo',
771 repoid=repo_name,)
799 repoid=repo_name,)
772 response = api_call(self, params)
800 response = api_call(self, params)
773
801
774 ret = {
802 ret = {
775 'msg': 'Deleted repository `%s`' % repo_name,
803 'msg': 'Deleted repository `%s`' % repo_name,
776 'success': True
804 'success': True
777 }
805 }
778 expected = ret
806 expected = ret
779 self._compare_ok(id_, expected, given=response.body)
807 self._compare_ok(id_, expected, given=response.body)
780
808
781 def test_api_delete_repo_by_non_admin(self):
809 def test_api_delete_repo_by_non_admin(self):
782 repo_name = 'api_delete_me'
810 repo_name = 'api_delete_me'
783 create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
811 create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
784 try:
812 try:
785 id_, params = _build_data(self.apikey_regular, 'delete_repo',
813 id_, params = _build_data(self.apikey_regular, 'delete_repo',
786 repoid=repo_name,)
814 repoid=repo_name,)
787 response = api_call(self, params)
815 response = api_call(self, params)
788
816
789 ret = {
817 ret = {
790 'msg': 'Deleted repository `%s`' % repo_name,
818 'msg': 'Deleted repository `%s`' % repo_name,
791 'success': True
819 'success': True
792 }
820 }
793 expected = ret
821 expected = ret
794 self._compare_ok(id_, expected, given=response.body)
822 self._compare_ok(id_, expected, given=response.body)
795 finally:
823 finally:
796 destroy_repo(repo_name)
824 destroy_repo(repo_name)
797
825
798 def test_api_delete_repo_by_non_admin_no_permission(self):
826 def test_api_delete_repo_by_non_admin_no_permission(self):
799 repo_name = 'api_delete_me'
827 repo_name = 'api_delete_me'
800 create_repo(repo_name, self.REPO_TYPE)
828 create_repo(repo_name, self.REPO_TYPE)
801 try:
829 try:
802 id_, params = _build_data(self.apikey_regular, 'delete_repo',
830 id_, params = _build_data(self.apikey_regular, 'delete_repo',
803 repoid=repo_name,)
831 repoid=repo_name,)
804 response = api_call(self, params)
832 response = api_call(self, params)
805 expected = 'repository `%s` does not exist' % (repo_name)
833 expected = 'repository `%s` does not exist' % (repo_name)
806 self._compare_error(id_, expected, given=response.body)
834 self._compare_error(id_, expected, given=response.body)
807 finally:
835 finally:
808 destroy_repo(repo_name)
836 destroy_repo(repo_name)
809
837
810 def test_api_delete_repo_exception_occurred(self):
838 def test_api_delete_repo_exception_occurred(self):
811 repo_name = 'api_delete_me'
839 repo_name = 'api_delete_me'
812 create_repo(repo_name, self.REPO_TYPE)
840 create_repo(repo_name, self.REPO_TYPE)
813 try:
841 try:
814 with mock.patch.object(RepoModel, 'delete', crash):
842 with mock.patch.object(RepoModel, 'delete', crash):
815 id_, params = _build_data(self.apikey, 'delete_repo',
843 id_, params = _build_data(self.apikey, 'delete_repo',
816 repoid=repo_name,)
844 repoid=repo_name,)
817 response = api_call(self, params)
845 response = api_call(self, params)
818
846
819 expected = 'failed to delete repository `%s`' % repo_name
847 expected = 'failed to delete repository `%s`' % repo_name
820 self._compare_error(id_, expected, given=response.body)
848 self._compare_error(id_, expected, given=response.body)
821 finally:
849 finally:
822 destroy_repo(repo_name)
850 destroy_repo(repo_name)
823
851
824 def test_api_fork_repo(self):
852 def test_api_fork_repo(self):
825 fork_name = 'api-repo-fork'
853 fork_name = 'api-repo-fork'
826 id_, params = _build_data(self.apikey, 'fork_repo',
854 id_, params = _build_data(self.apikey, 'fork_repo',
827 repoid=self.REPO,
855 repoid=self.REPO,
828 fork_name=fork_name,
856 fork_name=fork_name,
829 owner=TEST_USER_ADMIN_LOGIN,
857 owner=TEST_USER_ADMIN_LOGIN,
830 )
858 )
831 response = api_call(self, params)
859 response = api_call(self, params)
832
860
833 ret = {
861 ret = {
834 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
862 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
835 fork_name),
863 fork_name),
836 'success': True
864 'success': True
837 }
865 }
838 expected = ret
866 expected = ret
839 self._compare_ok(id_, expected, given=response.body)
867 self._compare_ok(id_, expected, given=response.body)
840 destroy_repo(fork_name)
868 destroy_repo(fork_name)
841
869
842 def test_api_fork_repo_non_admin(self):
870 def test_api_fork_repo_non_admin(self):
843 fork_name = 'api-repo-fork'
871 fork_name = 'api-repo-fork'
844 id_, params = _build_data(self.apikey_regular, 'fork_repo',
872 id_, params = _build_data(self.apikey_regular, 'fork_repo',
845 repoid=self.REPO,
873 repoid=self.REPO,
846 fork_name=fork_name,
874 fork_name=fork_name,
847 )
875 )
848 response = api_call(self, params)
876 response = api_call(self, params)
849
877
850 ret = {
878 ret = {
851 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
879 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
852 fork_name),
880 fork_name),
853 'success': True
881 'success': True
854 }
882 }
855 expected = ret
883 expected = ret
856 self._compare_ok(id_, expected, given=response.body)
884 self._compare_ok(id_, expected, given=response.body)
857 destroy_repo(fork_name)
885 destroy_repo(fork_name)
858
886
859 def test_api_fork_repo_non_admin_specify_owner(self):
887 def test_api_fork_repo_non_admin_specify_owner(self):
860 fork_name = 'api-repo-fork'
888 fork_name = 'api-repo-fork'
861 id_, params = _build_data(self.apikey_regular, 'fork_repo',
889 id_, params = _build_data(self.apikey_regular, 'fork_repo',
862 repoid=self.REPO,
890 repoid=self.REPO,
863 fork_name=fork_name,
891 fork_name=fork_name,
864 owner=TEST_USER_ADMIN_LOGIN,
892 owner=TEST_USER_ADMIN_LOGIN,
865 )
893 )
866 response = api_call(self, params)
894 response = api_call(self, params)
867 expected = 'Only RhodeCode admin can specify `owner` param'
895 expected = 'Only RhodeCode admin can specify `owner` param'
868 self._compare_error(id_, expected, given=response.body)
896 self._compare_error(id_, expected, given=response.body)
869 destroy_repo(fork_name)
897 destroy_repo(fork_name)
870
898
871 def test_api_fork_repo_non_admin_no_permission_to_fork(self):
899 def test_api_fork_repo_non_admin_no_permission_to_fork(self):
872 RepoModel().grant_user_permission(repo=self.REPO,
900 RepoModel().grant_user_permission(repo=self.REPO,
873 user=self.TEST_USER_LOGIN,
901 user=self.TEST_USER_LOGIN,
874 perm='repository.none')
902 perm='repository.none')
875 fork_name = 'api-repo-fork'
903 fork_name = 'api-repo-fork'
876 id_, params = _build_data(self.apikey_regular, 'fork_repo',
904 id_, params = _build_data(self.apikey_regular, 'fork_repo',
877 repoid=self.REPO,
905 repoid=self.REPO,
878 fork_name=fork_name,
906 fork_name=fork_name,
879 )
907 )
880 response = api_call(self, params)
908 response = api_call(self, params)
881 expected = 'repository `%s` does not exist' % (self.REPO)
909 expected = 'repository `%s` does not exist' % (self.REPO)
882 self._compare_error(id_, expected, given=response.body)
910 self._compare_error(id_, expected, given=response.body)
883 destroy_repo(fork_name)
911 destroy_repo(fork_name)
884
912
885 def test_api_fork_repo_unknown_owner(self):
913 def test_api_fork_repo_unknown_owner(self):
886 fork_name = 'api-repo-fork'
914 fork_name = 'api-repo-fork'
887 owner = 'i-dont-exist'
915 owner = 'i-dont-exist'
888 id_, params = _build_data(self.apikey, 'fork_repo',
916 id_, params = _build_data(self.apikey, 'fork_repo',
889 repoid=self.REPO,
917 repoid=self.REPO,
890 fork_name=fork_name,
918 fork_name=fork_name,
891 owner=owner,
919 owner=owner,
892 )
920 )
893 response = api_call(self, params)
921 response = api_call(self, params)
894 expected = 'user `%s` does not exist' % owner
922 expected = 'user `%s` does not exist' % owner
895 self._compare_error(id_, expected, given=response.body)
923 self._compare_error(id_, expected, given=response.body)
896
924
897 def test_api_fork_repo_fork_exists(self):
925 def test_api_fork_repo_fork_exists(self):
898 fork_name = 'api-repo-fork'
926 fork_name = 'api-repo-fork'
899 create_fork(fork_name, self.REPO_TYPE, self.REPO)
927 create_fork(fork_name, self.REPO_TYPE, self.REPO)
900
928
901 try:
929 try:
902 fork_name = 'api-repo-fork'
930 fork_name = 'api-repo-fork'
903
931
904 id_, params = _build_data(self.apikey, 'fork_repo',
932 id_, params = _build_data(self.apikey, 'fork_repo',
905 repoid=self.REPO,
933 repoid=self.REPO,
906 fork_name=fork_name,
934 fork_name=fork_name,
907 owner=TEST_USER_ADMIN_LOGIN,
935 owner=TEST_USER_ADMIN_LOGIN,
908 )
936 )
909 response = api_call(self, params)
937 response = api_call(self, params)
910
938
911 expected = "fork `%s` already exist" % fork_name
939 expected = "fork `%s` already exist" % fork_name
912 self._compare_error(id_, expected, given=response.body)
940 self._compare_error(id_, expected, given=response.body)
913 finally:
941 finally:
914 destroy_repo(fork_name)
942 destroy_repo(fork_name)
915
943
916 def test_api_fork_repo_repo_exists(self):
944 def test_api_fork_repo_repo_exists(self):
917 fork_name = self.REPO
945 fork_name = self.REPO
918
946
919 id_, params = _build_data(self.apikey, 'fork_repo',
947 id_, params = _build_data(self.apikey, 'fork_repo',
920 repoid=self.REPO,
948 repoid=self.REPO,
921 fork_name=fork_name,
949 fork_name=fork_name,
922 owner=TEST_USER_ADMIN_LOGIN,
950 owner=TEST_USER_ADMIN_LOGIN,
923 )
951 )
924 response = api_call(self, params)
952 response = api_call(self, params)
925
953
926 expected = "repo `%s` already exist" % fork_name
954 expected = "repo `%s` already exist" % fork_name
927 self._compare_error(id_, expected, given=response.body)
955 self._compare_error(id_, expected, given=response.body)
928
956
929 @mock.patch.object(RepoModel, 'create_fork', crash)
957 @mock.patch.object(RepoModel, 'create_fork', crash)
930 def test_api_fork_repo_exception_occurred(self):
958 def test_api_fork_repo_exception_occurred(self):
931 fork_name = 'api-repo-fork'
959 fork_name = 'api-repo-fork'
932 id_, params = _build_data(self.apikey, 'fork_repo',
960 id_, params = _build_data(self.apikey, 'fork_repo',
933 repoid=self.REPO,
961 repoid=self.REPO,
934 fork_name=fork_name,
962 fork_name=fork_name,
935 owner=TEST_USER_ADMIN_LOGIN,
963 owner=TEST_USER_ADMIN_LOGIN,
936 )
964 )
937 response = api_call(self, params)
965 response = api_call(self, params)
938
966
939 expected = 'failed to fork repository `%s` as `%s`' % (self.REPO,
967 expected = 'failed to fork repository `%s` as `%s`' % (self.REPO,
940 fork_name)
968 fork_name)
941 self._compare_error(id_, expected, given=response.body)
969 self._compare_error(id_, expected, given=response.body)
942
970
943 def test_api_get_users_group(self):
971 def test_api_get_users_group(self):
944 id_, params = _build_data(self.apikey, 'get_users_group',
972 id_, params = _build_data(self.apikey, 'get_users_group',
945 usersgroupid=TEST_USERS_GROUP)
973 usersgroupid=TEST_USERS_GROUP)
946 response = api_call(self, params)
974 response = api_call(self, params)
947
975
948 users_group = UsersGroupModel().get_group(TEST_USERS_GROUP)
976 users_group = UsersGroupModel().get_group(TEST_USERS_GROUP)
949 members = []
977 members = []
950 for user in users_group.members:
978 for user in users_group.members:
951 user = user.user
979 user = user.user
952 members.append(user.get_api_data())
980 members.append(user.get_api_data())
953
981
954 ret = users_group.get_api_data()
982 ret = users_group.get_api_data()
955 ret['members'] = members
983 ret['members'] = members
956 expected = ret
984 expected = ret
957 self._compare_ok(id_, expected, given=response.body)
985 self._compare_ok(id_, expected, given=response.body)
958
986
959 def test_api_get_users_groups(self):
987 def test_api_get_users_groups(self):
960
988
961 make_users_group('test_users_group2')
989 make_users_group('test_users_group2')
962
990
963 id_, params = _build_data(self.apikey, 'get_users_groups',)
991 id_, params = _build_data(self.apikey, 'get_users_groups',)
964 response = api_call(self, params)
992 response = api_call(self, params)
965
993
966 expected = []
994 expected = []
967 for gr_name in [TEST_USERS_GROUP, 'test_users_group2']:
995 for gr_name in [TEST_USERS_GROUP, 'test_users_group2']:
968 users_group = UsersGroupModel().get_group(gr_name)
996 users_group = UsersGroupModel().get_group(gr_name)
969 ret = users_group.get_api_data()
997 ret = users_group.get_api_data()
970 expected.append(ret)
998 expected.append(ret)
971 self._compare_ok(id_, expected, given=response.body)
999 self._compare_ok(id_, expected, given=response.body)
972
1000
973 UsersGroupModel().delete(users_group='test_users_group2')
1001 UsersGroupModel().delete(users_group='test_users_group2')
974 Session().commit()
1002 Session().commit()
975
1003
976 def test_api_create_users_group(self):
1004 def test_api_create_users_group(self):
977 group_name = 'some_new_group'
1005 group_name = 'some_new_group'
978 id_, params = _build_data(self.apikey, 'create_users_group',
1006 id_, params = _build_data(self.apikey, 'create_users_group',
979 group_name=group_name)
1007 group_name=group_name)
980 response = api_call(self, params)
1008 response = api_call(self, params)
981
1009
982 ret = {
1010 ret = {
983 'msg': 'created new users group `%s`' % group_name,
1011 'msg': 'created new users group `%s`' % group_name,
984 'users_group': jsonify(UsersGroupModel()\
1012 'users_group': jsonify(UsersGroupModel()\
985 .get_by_name(group_name)\
1013 .get_by_name(group_name)\
986 .get_api_data())
1014 .get_api_data())
987 }
1015 }
988 expected = ret
1016 expected = ret
989 self._compare_ok(id_, expected, given=response.body)
1017 self._compare_ok(id_, expected, given=response.body)
990
1018
991 destroy_users_group(group_name)
1019 destroy_users_group(group_name)
992
1020
993 def test_api_get_users_group_that_exist(self):
1021 def test_api_get_users_group_that_exist(self):
994 id_, params = _build_data(self.apikey, 'create_users_group',
1022 id_, params = _build_data(self.apikey, 'create_users_group',
995 group_name=TEST_USERS_GROUP)
1023 group_name=TEST_USERS_GROUP)
996 response = api_call(self, params)
1024 response = api_call(self, params)
997
1025
998 expected = "users group `%s` already exist" % TEST_USERS_GROUP
1026 expected = "users group `%s` already exist" % TEST_USERS_GROUP
999 self._compare_error(id_, expected, given=response.body)
1027 self._compare_error(id_, expected, given=response.body)
1000
1028
1001 @mock.patch.object(UsersGroupModel, 'create', crash)
1029 @mock.patch.object(UsersGroupModel, 'create', crash)
1002 def test_api_get_users_group_exception_occurred(self):
1030 def test_api_get_users_group_exception_occurred(self):
1003 group_name = 'exception_happens'
1031 group_name = 'exception_happens'
1004 id_, params = _build_data(self.apikey, 'create_users_group',
1032 id_, params = _build_data(self.apikey, 'create_users_group',
1005 group_name=group_name)
1033 group_name=group_name)
1006 response = api_call(self, params)
1034 response = api_call(self, params)
1007
1035
1008 expected = 'failed to create group `%s`' % group_name
1036 expected = 'failed to create group `%s`' % group_name
1009 self._compare_error(id_, expected, given=response.body)
1037 self._compare_error(id_, expected, given=response.body)
1010
1038
1011 def test_api_add_user_to_users_group(self):
1039 def test_api_add_user_to_users_group(self):
1012 gr_name = 'test_group'
1040 gr_name = 'test_group'
1013 UsersGroupModel().create(gr_name)
1041 UsersGroupModel().create(gr_name)
1014 Session().commit()
1042 Session().commit()
1015 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1043 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1016 usersgroupid=gr_name,
1044 usersgroupid=gr_name,
1017 userid=TEST_USER_ADMIN_LOGIN)
1045 userid=TEST_USER_ADMIN_LOGIN)
1018 response = api_call(self, params)
1046 response = api_call(self, params)
1019
1047
1020 expected = {
1048 expected = {
1021 'msg': 'added member `%s` to users group `%s`' % (
1049 'msg': 'added member `%s` to users group `%s`' % (
1022 TEST_USER_ADMIN_LOGIN, gr_name
1050 TEST_USER_ADMIN_LOGIN, gr_name
1023 ),
1051 ),
1024 'success': True}
1052 'success': True}
1025 self._compare_ok(id_, expected, given=response.body)
1053 self._compare_ok(id_, expected, given=response.body)
1026
1054
1027 UsersGroupModel().delete(users_group=gr_name)
1055 UsersGroupModel().delete(users_group=gr_name)
1028 Session().commit()
1056 Session().commit()
1029
1057
1030 def test_api_add_user_to_users_group_that_doesnt_exist(self):
1058 def test_api_add_user_to_users_group_that_doesnt_exist(self):
1031 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1059 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1032 usersgroupid='false-group',
1060 usersgroupid='false-group',
1033 userid=TEST_USER_ADMIN_LOGIN)
1061 userid=TEST_USER_ADMIN_LOGIN)
1034 response = api_call(self, params)
1062 response = api_call(self, params)
1035
1063
1036 expected = 'users group `%s` does not exist' % 'false-group'
1064 expected = 'users group `%s` does not exist' % 'false-group'
1037 self._compare_error(id_, expected, given=response.body)
1065 self._compare_error(id_, expected, given=response.body)
1038
1066
1039 @mock.patch.object(UsersGroupModel, 'add_user_to_group', crash)
1067 @mock.patch.object(UsersGroupModel, 'add_user_to_group', crash)
1040 def test_api_add_user_to_users_group_exception_occurred(self):
1068 def test_api_add_user_to_users_group_exception_occurred(self):
1041 gr_name = 'test_group'
1069 gr_name = 'test_group'
1042 UsersGroupModel().create(gr_name)
1070 UsersGroupModel().create(gr_name)
1043 Session().commit()
1071 Session().commit()
1044 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1072 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1045 usersgroupid=gr_name,
1073 usersgroupid=gr_name,
1046 userid=TEST_USER_ADMIN_LOGIN)
1074 userid=TEST_USER_ADMIN_LOGIN)
1047 response = api_call(self, params)
1075 response = api_call(self, params)
1048
1076
1049 expected = 'failed to add member to users group `%s`' % gr_name
1077 expected = 'failed to add member to users group `%s`' % gr_name
1050 self._compare_error(id_, expected, given=response.body)
1078 self._compare_error(id_, expected, given=response.body)
1051
1079
1052 UsersGroupModel().delete(users_group=gr_name)
1080 UsersGroupModel().delete(users_group=gr_name)
1053 Session().commit()
1081 Session().commit()
1054
1082
1055 def test_api_remove_user_from_users_group(self):
1083 def test_api_remove_user_from_users_group(self):
1056 gr_name = 'test_group_3'
1084 gr_name = 'test_group_3'
1057 gr = UsersGroupModel().create(gr_name)
1085 gr = UsersGroupModel().create(gr_name)
1058 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1086 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1059 Session().commit()
1087 Session().commit()
1060 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
1088 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
1061 usersgroupid=gr_name,
1089 usersgroupid=gr_name,
1062 userid=TEST_USER_ADMIN_LOGIN)
1090 userid=TEST_USER_ADMIN_LOGIN)
1063 response = api_call(self, params)
1091 response = api_call(self, params)
1064
1092
1065 expected = {
1093 expected = {
1066 'msg': 'removed member `%s` from users group `%s`' % (
1094 'msg': 'removed member `%s` from users group `%s`' % (
1067 TEST_USER_ADMIN_LOGIN, gr_name
1095 TEST_USER_ADMIN_LOGIN, gr_name
1068 ),
1096 ),
1069 'success': True}
1097 'success': True}
1070 self._compare_ok(id_, expected, given=response.body)
1098 self._compare_ok(id_, expected, given=response.body)
1071
1099
1072 UsersGroupModel().delete(users_group=gr_name)
1100 UsersGroupModel().delete(users_group=gr_name)
1073 Session().commit()
1101 Session().commit()
1074
1102
1075 @mock.patch.object(UsersGroupModel, 'remove_user_from_group', crash)
1103 @mock.patch.object(UsersGroupModel, 'remove_user_from_group', crash)
1076 def test_api_remove_user_from_users_group_exception_occurred(self):
1104 def test_api_remove_user_from_users_group_exception_occurred(self):
1077 gr_name = 'test_group_3'
1105 gr_name = 'test_group_3'
1078 gr = UsersGroupModel().create(gr_name)
1106 gr = UsersGroupModel().create(gr_name)
1079 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1107 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1080 Session().commit()
1108 Session().commit()
1081 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
1109 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
1082 usersgroupid=gr_name,
1110 usersgroupid=gr_name,
1083 userid=TEST_USER_ADMIN_LOGIN)
1111 userid=TEST_USER_ADMIN_LOGIN)
1084 response = api_call(self, params)
1112 response = api_call(self, params)
1085
1113
1086 expected = 'failed to remove member from users group `%s`' % gr_name
1114 expected = 'failed to remove member from users group `%s`' % gr_name
1087 self._compare_error(id_, expected, given=response.body)
1115 self._compare_error(id_, expected, given=response.body)
1088
1116
1089 UsersGroupModel().delete(users_group=gr_name)
1117 UsersGroupModel().delete(users_group=gr_name)
1090 Session().commit()
1118 Session().commit()
1091
1119
1092 @parameterized.expand([('none', 'repository.none'),
1120 @parameterized.expand([('none', 'repository.none'),
1093 ('read', 'repository.read'),
1121 ('read', 'repository.read'),
1094 ('write', 'repository.write'),
1122 ('write', 'repository.write'),
1095 ('admin', 'repository.admin')])
1123 ('admin', 'repository.admin')])
1096 def test_api_grant_user_permission(self, name, perm):
1124 def test_api_grant_user_permission(self, name, perm):
1097 id_, params = _build_data(self.apikey, 'grant_user_permission',
1125 id_, params = _build_data(self.apikey, 'grant_user_permission',
1098 repoid=self.REPO,
1126 repoid=self.REPO,
1099 userid=TEST_USER_ADMIN_LOGIN,
1127 userid=TEST_USER_ADMIN_LOGIN,
1100 perm=perm)
1128 perm=perm)
1101 response = api_call(self, params)
1129 response = api_call(self, params)
1102
1130
1103 ret = {
1131 ret = {
1104 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % (
1132 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % (
1105 perm, TEST_USER_ADMIN_LOGIN, self.REPO
1133 perm, TEST_USER_ADMIN_LOGIN, self.REPO
1106 ),
1134 ),
1107 'success': True
1135 'success': True
1108 }
1136 }
1109 expected = ret
1137 expected = ret
1110 self._compare_ok(id_, expected, given=response.body)
1138 self._compare_ok(id_, expected, given=response.body)
1111
1139
1112 def test_api_grant_user_permission_wrong_permission(self):
1140 def test_api_grant_user_permission_wrong_permission(self):
1113 perm = 'haha.no.permission'
1141 perm = 'haha.no.permission'
1114 id_, params = _build_data(self.apikey, 'grant_user_permission',
1142 id_, params = _build_data(self.apikey, 'grant_user_permission',
1115 repoid=self.REPO,
1143 repoid=self.REPO,
1116 userid=TEST_USER_ADMIN_LOGIN,
1144 userid=TEST_USER_ADMIN_LOGIN,
1117 perm=perm)
1145 perm=perm)
1118 response = api_call(self, params)
1146 response = api_call(self, params)
1119
1147
1120 expected = 'permission `%s` does not exist' % perm
1148 expected = 'permission `%s` does not exist' % perm
1121 self._compare_error(id_, expected, given=response.body)
1149 self._compare_error(id_, expected, given=response.body)
1122
1150
1123 @mock.patch.object(RepoModel, 'grant_user_permission', crash)
1151 @mock.patch.object(RepoModel, 'grant_user_permission', crash)
1124 def test_api_grant_user_permission_exception_when_adding(self):
1152 def test_api_grant_user_permission_exception_when_adding(self):
1125 perm = 'repository.read'
1153 perm = 'repository.read'
1126 id_, params = _build_data(self.apikey, 'grant_user_permission',
1154 id_, params = _build_data(self.apikey, 'grant_user_permission',
1127 repoid=self.REPO,
1155 repoid=self.REPO,
1128 userid=TEST_USER_ADMIN_LOGIN,
1156 userid=TEST_USER_ADMIN_LOGIN,
1129 perm=perm)
1157 perm=perm)
1130 response = api_call(self, params)
1158 response = api_call(self, params)
1131
1159
1132 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
1160 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
1133 TEST_USER_ADMIN_LOGIN, self.REPO
1161 TEST_USER_ADMIN_LOGIN, self.REPO
1134 )
1162 )
1135 self._compare_error(id_, expected, given=response.body)
1163 self._compare_error(id_, expected, given=response.body)
1136
1164
1137 def test_api_revoke_user_permission(self):
1165 def test_api_revoke_user_permission(self):
1138 id_, params = _build_data(self.apikey, 'revoke_user_permission',
1166 id_, params = _build_data(self.apikey, 'revoke_user_permission',
1139 repoid=self.REPO,
1167 repoid=self.REPO,
1140 userid=TEST_USER_ADMIN_LOGIN,)
1168 userid=TEST_USER_ADMIN_LOGIN,)
1141 response = api_call(self, params)
1169 response = api_call(self, params)
1142
1170
1143 expected = {
1171 expected = {
1144 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
1172 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
1145 TEST_USER_ADMIN_LOGIN, self.REPO
1173 TEST_USER_ADMIN_LOGIN, self.REPO
1146 ),
1174 ),
1147 'success': True
1175 'success': True
1148 }
1176 }
1149 self._compare_ok(id_, expected, given=response.body)
1177 self._compare_ok(id_, expected, given=response.body)
1150
1178
1151 @mock.patch.object(RepoModel, 'revoke_user_permission', crash)
1179 @mock.patch.object(RepoModel, 'revoke_user_permission', crash)
1152 def test_api_revoke_user_permission_exception_when_adding(self):
1180 def test_api_revoke_user_permission_exception_when_adding(self):
1153 id_, params = _build_data(self.apikey, 'revoke_user_permission',
1181 id_, params = _build_data(self.apikey, 'revoke_user_permission',
1154 repoid=self.REPO,
1182 repoid=self.REPO,
1155 userid=TEST_USER_ADMIN_LOGIN,)
1183 userid=TEST_USER_ADMIN_LOGIN,)
1156 response = api_call(self, params)
1184 response = api_call(self, params)
1157
1185
1158 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
1186 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
1159 TEST_USER_ADMIN_LOGIN, self.REPO
1187 TEST_USER_ADMIN_LOGIN, self.REPO
1160 )
1188 )
1161 self._compare_error(id_, expected, given=response.body)
1189 self._compare_error(id_, expected, given=response.body)
1162
1190
1163 @parameterized.expand([('none', 'repository.none'),
1191 @parameterized.expand([('none', 'repository.none'),
1164 ('read', 'repository.read'),
1192 ('read', 'repository.read'),
1165 ('write', 'repository.write'),
1193 ('write', 'repository.write'),
1166 ('admin', 'repository.admin')])
1194 ('admin', 'repository.admin')])
1167 def test_api_grant_users_group_permission(self, name, perm):
1195 def test_api_grant_users_group_permission(self, name, perm):
1168 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1196 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1169 repoid=self.REPO,
1197 repoid=self.REPO,
1170 usersgroupid=TEST_USERS_GROUP,
1198 usersgroupid=TEST_USERS_GROUP,
1171 perm=perm)
1199 perm=perm)
1172 response = api_call(self, params)
1200 response = api_call(self, params)
1173
1201
1174 ret = {
1202 ret = {
1175 'msg': 'Granted perm: `%s` for users group: `%s` in repo: `%s`' % (
1203 'msg': 'Granted perm: `%s` for users group: `%s` in repo: `%s`' % (
1176 perm, TEST_USERS_GROUP, self.REPO
1204 perm, TEST_USERS_GROUP, self.REPO
1177 ),
1205 ),
1178 'success': True
1206 'success': True
1179 }
1207 }
1180 expected = ret
1208 expected = ret
1181 self._compare_ok(id_, expected, given=response.body)
1209 self._compare_ok(id_, expected, given=response.body)
1182
1210
1183 def test_api_grant_users_group_permission_wrong_permission(self):
1211 def test_api_grant_users_group_permission_wrong_permission(self):
1184 perm = 'haha.no.permission'
1212 perm = 'haha.no.permission'
1185 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1213 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1186 repoid=self.REPO,
1214 repoid=self.REPO,
1187 usersgroupid=TEST_USERS_GROUP,
1215 usersgroupid=TEST_USERS_GROUP,
1188 perm=perm)
1216 perm=perm)
1189 response = api_call(self, params)
1217 response = api_call(self, params)
1190
1218
1191 expected = 'permission `%s` does not exist' % perm
1219 expected = 'permission `%s` does not exist' % perm
1192 self._compare_error(id_, expected, given=response.body)
1220 self._compare_error(id_, expected, given=response.body)
1193
1221
1194 @mock.patch.object(RepoModel, 'grant_users_group_permission', crash)
1222 @mock.patch.object(RepoModel, 'grant_users_group_permission', crash)
1195 def test_api_grant_users_group_permission_exception_when_adding(self):
1223 def test_api_grant_users_group_permission_exception_when_adding(self):
1196 perm = 'repository.read'
1224 perm = 'repository.read'
1197 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1225 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1198 repoid=self.REPO,
1226 repoid=self.REPO,
1199 usersgroupid=TEST_USERS_GROUP,
1227 usersgroupid=TEST_USERS_GROUP,
1200 perm=perm)
1228 perm=perm)
1201 response = api_call(self, params)
1229 response = api_call(self, params)
1202
1230
1203 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
1231 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
1204 TEST_USERS_GROUP, self.REPO
1232 TEST_USERS_GROUP, self.REPO
1205 )
1233 )
1206 self._compare_error(id_, expected, given=response.body)
1234 self._compare_error(id_, expected, given=response.body)
1207
1235
1208 def test_api_revoke_users_group_permission(self):
1236 def test_api_revoke_users_group_permission(self):
1209 RepoModel().grant_users_group_permission(repo=self.REPO,
1237 RepoModel().grant_users_group_permission(repo=self.REPO,
1210 group_name=TEST_USERS_GROUP,
1238 group_name=TEST_USERS_GROUP,
1211 perm='repository.read')
1239 perm='repository.read')
1212 Session().commit()
1240 Session().commit()
1213 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1241 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1214 repoid=self.REPO,
1242 repoid=self.REPO,
1215 usersgroupid=TEST_USERS_GROUP,)
1243 usersgroupid=TEST_USERS_GROUP,)
1216 response = api_call(self, params)
1244 response = api_call(self, params)
1217
1245
1218 expected = {
1246 expected = {
1219 'msg': 'Revoked perm for users group: `%s` in repo: `%s`' % (
1247 'msg': 'Revoked perm for users group: `%s` in repo: `%s`' % (
1220 TEST_USERS_GROUP, self.REPO
1248 TEST_USERS_GROUP, self.REPO
1221 ),
1249 ),
1222 'success': True
1250 'success': True
1223 }
1251 }
1224 self._compare_ok(id_, expected, given=response.body)
1252 self._compare_ok(id_, expected, given=response.body)
1225
1253
1226 @mock.patch.object(RepoModel, 'revoke_users_group_permission', crash)
1254 @mock.patch.object(RepoModel, 'revoke_users_group_permission', crash)
1227 def test_api_revoke_users_group_permission_exception_when_adding(self):
1255 def test_api_revoke_users_group_permission_exception_when_adding(self):
1228
1256
1229 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1257 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1230 repoid=self.REPO,
1258 repoid=self.REPO,
1231 usersgroupid=TEST_USERS_GROUP,)
1259 usersgroupid=TEST_USERS_GROUP,)
1232 response = api_call(self, params)
1260 response = api_call(self, params)
1233
1261
1234 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
1262 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
1235 TEST_USERS_GROUP, self.REPO
1263 TEST_USERS_GROUP, self.REPO
1236 )
1264 )
1237 self._compare_error(id_, expected, given=response.body)
1265 self._compare_error(id_, expected, given=response.body)
General Comments 0
You need to be logged in to leave comments. Login now