##// END OF EJS Templates
Remove translation calls in API
marcink -
r3884:31f8c9d7 beta
parent child Browse files
Show More
@@ -1,1109 +1,1109 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.api
3 rhodecode.controllers.api
4 ~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 API controller for RhodeCode
6 API controller for RhodeCode
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 time
28 import time
29 import traceback
29 import traceback
30 import logging
30 import logging
31
31
32 from rhodecode.controllers.api import JSONRPCController, JSONRPCError
32 from rhodecode.controllers.api import JSONRPCController, JSONRPCError
33 from rhodecode.lib.auth import PasswordGenerator, AuthUser, \
33 from rhodecode.lib.auth import PasswordGenerator, AuthUser, \
34 HasPermissionAllDecorator, HasPermissionAnyDecorator, \
34 HasPermissionAllDecorator, HasPermissionAnyDecorator, \
35 HasPermissionAnyApi, HasRepoPermissionAnyApi
35 HasPermissionAnyApi, HasRepoPermissionAnyApi
36 from rhodecode.lib.utils import map_groups, repo2db_mapper
36 from rhodecode.lib.utils import map_groups, repo2db_mapper
37 from rhodecode.lib.utils2 import str2bool, time_to_datetime, safe_int
37 from rhodecode.lib.utils2 import str2bool, time_to_datetime, safe_int
38 from rhodecode.lib import helpers as h
38 from rhodecode.lib import helpers as h
39 from rhodecode.model.meta import Session
39 from rhodecode.model.meta import Session
40 from rhodecode.model.scm import ScmModel
40 from rhodecode.model.scm import ScmModel
41 from rhodecode.model.repo import RepoModel
41 from rhodecode.model.repo import RepoModel
42 from rhodecode.model.user import UserModel
42 from rhodecode.model.user import UserModel
43 from rhodecode.model.users_group import UserGroupModel
43 from rhodecode.model.users_group import UserGroupModel
44 from rhodecode.model.db import Repository, RhodeCodeSetting, UserIpMap,\
44 from rhodecode.model.db import Repository, RhodeCodeSetting, UserIpMap,\
45 Permission, User, Gist
45 Permission, User, Gist
46 from rhodecode.lib.compat import json
46 from rhodecode.lib.compat import json
47 from rhodecode.lib.exceptions import DefaultUserException
47 from rhodecode.lib.exceptions import DefaultUserException
48 from rhodecode.model.gist import GistModel
48 from rhodecode.model.gist import GistModel
49
49
50 log = logging.getLogger(__name__)
50 log = logging.getLogger(__name__)
51
51
52
52
53 class OptionalAttr(object):
53 class OptionalAttr(object):
54 """
54 """
55 Special Optional Option that defines other attribute
55 Special Optional Option that defines other attribute
56 """
56 """
57 def __init__(self, attr_name):
57 def __init__(self, attr_name):
58 self.attr_name = attr_name
58 self.attr_name = attr_name
59
59
60 def __repr__(self):
60 def __repr__(self):
61 return '<OptionalAttr:%s>' % self.attr_name
61 return '<OptionalAttr:%s>' % self.attr_name
62
62
63 def __call__(self):
63 def __call__(self):
64 return self
64 return self
65 #alias
65 #alias
66 OAttr = OptionalAttr
66 OAttr = OptionalAttr
67
67
68
68
69 class Optional(object):
69 class Optional(object):
70 """
70 """
71 Defines an optional parameter::
71 Defines an optional parameter::
72
72
73 param = param.getval() if isinstance(param, Optional) else param
73 param = param.getval() if isinstance(param, Optional) else param
74 param = param() if isinstance(param, Optional) else param
74 param = param() if isinstance(param, Optional) else param
75
75
76 is equivalent of::
76 is equivalent of::
77
77
78 param = Optional.extract(param)
78 param = Optional.extract(param)
79
79
80 """
80 """
81 def __init__(self, type_):
81 def __init__(self, type_):
82 self.type_ = type_
82 self.type_ = type_
83
83
84 def __repr__(self):
84 def __repr__(self):
85 return '<Optional:%s>' % self.type_.__repr__()
85 return '<Optional:%s>' % self.type_.__repr__()
86
86
87 def __call__(self):
87 def __call__(self):
88 return self.getval()
88 return self.getval()
89
89
90 def getval(self):
90 def getval(self):
91 """
91 """
92 returns value from this Optional instance
92 returns value from this Optional instance
93 """
93 """
94 return self.type_
94 return self.type_
95
95
96 @classmethod
96 @classmethod
97 def extract(cls, val):
97 def extract(cls, val):
98 if isinstance(val, cls):
98 if isinstance(val, cls):
99 return val.getval()
99 return val.getval()
100 return val
100 return val
101
101
102
102
103 def get_user_or_error(userid):
103 def get_user_or_error(userid):
104 """
104 """
105 Get user by id or name or return JsonRPCError if not found
105 Get user by id or name or return JsonRPCError if not found
106
106
107 :param userid:
107 :param userid:
108 """
108 """
109 user = UserModel().get_user(userid)
109 user = UserModel().get_user(userid)
110 if user is None:
110 if user is None:
111 raise JSONRPCError("user `%s` does not exist" % userid)
111 raise JSONRPCError("user `%s` does not exist" % userid)
112 return user
112 return user
113
113
114
114
115 def get_repo_or_error(repoid):
115 def get_repo_or_error(repoid):
116 """
116 """
117 Get repo by id or name or return JsonRPCError if not found
117 Get repo by id or name or return JsonRPCError if not found
118
118
119 :param userid:
119 :param userid:
120 """
120 """
121 repo = RepoModel().get_repo(repoid)
121 repo = RepoModel().get_repo(repoid)
122 if repo is None:
122 if repo is None:
123 raise JSONRPCError('repository `%s` does not exist' % (repoid))
123 raise JSONRPCError('repository `%s` does not exist' % (repoid))
124 return repo
124 return repo
125
125
126
126
127 def get_users_group_or_error(usersgroupid):
127 def get_users_group_or_error(usersgroupid):
128 """
128 """
129 Get user group by id or name or return JsonRPCError if not found
129 Get user group by id or name or return JsonRPCError if not found
130
130
131 :param userid:
131 :param userid:
132 """
132 """
133 users_group = UserGroupModel().get_group(usersgroupid)
133 users_group = UserGroupModel().get_group(usersgroupid)
134 if users_group is None:
134 if users_group is None:
135 raise JSONRPCError('user group `%s` does not exist' % usersgroupid)
135 raise JSONRPCError('user group `%s` does not exist' % usersgroupid)
136 return users_group
136 return users_group
137
137
138
138
139 def get_perm_or_error(permid):
139 def get_perm_or_error(permid):
140 """
140 """
141 Get permission by id or name or return JsonRPCError if not found
141 Get permission by id or name or return JsonRPCError if not found
142
142
143 :param userid:
143 :param userid:
144 """
144 """
145 perm = Permission.get_by_key(permid)
145 perm = Permission.get_by_key(permid)
146 if perm is None:
146 if perm is None:
147 raise JSONRPCError('permission `%s` does not exist' % (permid))
147 raise JSONRPCError('permission `%s` does not exist' % (permid))
148 return perm
148 return perm
149
149
150
150
151 class ApiController(JSONRPCController):
151 class ApiController(JSONRPCController):
152 """
152 """
153 API Controller
153 API Controller
154
154
155
155
156 Each method needs to have USER as argument this is then based on given
156 Each method needs to have USER as argument this is then based on given
157 API_KEY propagated as instance of user object
157 API_KEY propagated as instance of user object
158
158
159 Preferably this should be first argument also
159 Preferably this should be first argument also
160
160
161
161
162 Each function should also **raise** JSONRPCError for any
162 Each function should also **raise** JSONRPCError for any
163 errors that happens
163 errors that happens
164
164
165 """
165 """
166
166
167 @HasPermissionAllDecorator('hg.admin')
167 @HasPermissionAllDecorator('hg.admin')
168 def pull(self, apiuser, repoid):
168 def pull(self, apiuser, repoid):
169 """
169 """
170 Dispatch pull action on given repo
170 Dispatch pull action on given repo
171
171
172 :param apiuser:
172 :param apiuser:
173 :param repoid:
173 :param repoid:
174 """
174 """
175
175
176 repo = get_repo_or_error(repoid)
176 repo = get_repo_or_error(repoid)
177
177
178 try:
178 try:
179 ScmModel().pull_changes(repo.repo_name,
179 ScmModel().pull_changes(repo.repo_name,
180 self.rhodecode_user.username)
180 self.rhodecode_user.username)
181 return 'Pulled from `%s`' % repo.repo_name
181 return 'Pulled from `%s`' % repo.repo_name
182 except Exception:
182 except Exception:
183 log.error(traceback.format_exc())
183 log.error(traceback.format_exc())
184 raise JSONRPCError(
184 raise JSONRPCError(
185 'Unable to pull changes from `%s`' % repo.repo_name
185 'Unable to pull changes from `%s`' % repo.repo_name
186 )
186 )
187
187
188 @HasPermissionAllDecorator('hg.admin')
188 @HasPermissionAllDecorator('hg.admin')
189 def rescan_repos(self, apiuser, remove_obsolete=Optional(False)):
189 def rescan_repos(self, apiuser, remove_obsolete=Optional(False)):
190 """
190 """
191 Dispatch rescan repositories action. If remove_obsolete is set
191 Dispatch rescan repositories action. If remove_obsolete is set
192 than also delete repos that are in database but not in the filesystem.
192 than also delete repos that are in database but not in the filesystem.
193 aka "clean zombies"
193 aka "clean zombies"
194
194
195 :param apiuser:
195 :param apiuser:
196 :param remove_obsolete:
196 :param remove_obsolete:
197 """
197 """
198
198
199 try:
199 try:
200 rm_obsolete = Optional.extract(remove_obsolete)
200 rm_obsolete = Optional.extract(remove_obsolete)
201 added, removed = repo2db_mapper(ScmModel().repo_scan(),
201 added, removed = repo2db_mapper(ScmModel().repo_scan(),
202 remove_obsolete=rm_obsolete)
202 remove_obsolete=rm_obsolete)
203 return {'added': added, 'removed': removed}
203 return {'added': added, 'removed': removed}
204 except Exception:
204 except Exception:
205 log.error(traceback.format_exc())
205 log.error(traceback.format_exc())
206 raise JSONRPCError(
206 raise JSONRPCError(
207 'Error occurred during rescan repositories action'
207 'Error occurred during rescan repositories action'
208 )
208 )
209
209
210 def invalidate_cache(self, apiuser, repoid):
210 def invalidate_cache(self, apiuser, repoid):
211 """
211 """
212 Dispatch cache invalidation action on given repo
212 Dispatch cache invalidation action on given repo
213
213
214 :param apiuser:
214 :param apiuser:
215 :param repoid:
215 :param repoid:
216 """
216 """
217 repo = get_repo_or_error(repoid)
217 repo = get_repo_or_error(repoid)
218 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
218 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
219 # check if we have admin permission for this repo !
219 # check if we have admin permission for this repo !
220 if HasRepoPermissionAnyApi('repository.admin',
220 if HasRepoPermissionAnyApi('repository.admin',
221 'repository.write')(user=apiuser,
221 'repository.write')(user=apiuser,
222 repo_name=repo.repo_name) is False:
222 repo_name=repo.repo_name) is False:
223 raise JSONRPCError('repository `%s` does not exist' % (repoid))
223 raise JSONRPCError('repository `%s` does not exist' % (repoid))
224
224
225 try:
225 try:
226 ScmModel().mark_for_invalidation(repo.repo_name)
226 ScmModel().mark_for_invalidation(repo.repo_name)
227 return ('Caches of repository `%s` was invalidated' % repoid)
227 return ('Caches of repository `%s` was invalidated' % repoid)
228 except Exception:
228 except Exception:
229 log.error(traceback.format_exc())
229 log.error(traceback.format_exc())
230 raise JSONRPCError(
230 raise JSONRPCError(
231 'Error occurred during cache invalidation action'
231 'Error occurred during cache invalidation action'
232 )
232 )
233
233
234 def lock(self, apiuser, repoid, locked=Optional(None),
234 def lock(self, apiuser, repoid, locked=Optional(None),
235 userid=Optional(OAttr('apiuser'))):
235 userid=Optional(OAttr('apiuser'))):
236 """
236 """
237 Set locking state on particular repository by given user, if
237 Set locking state on particular repository by given user, if
238 this command is runned by non-admin account userid is set to user
238 this command is runned by non-admin account userid is set to user
239 who is calling this method
239 who is calling this method
240
240
241 :param apiuser:
241 :param apiuser:
242 :param repoid:
242 :param repoid:
243 :param userid:
243 :param userid:
244 :param locked:
244 :param locked:
245 """
245 """
246 repo = get_repo_or_error(repoid)
246 repo = get_repo_or_error(repoid)
247 if HasPermissionAnyApi('hg.admin')(user=apiuser):
247 if HasPermissionAnyApi('hg.admin')(user=apiuser):
248 pass
248 pass
249 elif HasRepoPermissionAnyApi('repository.admin',
249 elif HasRepoPermissionAnyApi('repository.admin',
250 'repository.write')(user=apiuser,
250 'repository.write')(user=apiuser,
251 repo_name=repo.repo_name):
251 repo_name=repo.repo_name):
252 #make sure normal user does not pass someone else userid,
252 #make sure normal user does not pass someone else userid,
253 #he is not allowed to do that
253 #he is not allowed to do that
254 if not isinstance(userid, Optional) and userid != apiuser.user_id:
254 if not isinstance(userid, Optional) and userid != apiuser.user_id:
255 raise JSONRPCError(
255 raise JSONRPCError(
256 'userid is not the same as your user'
256 'userid is not the same as your user'
257 )
257 )
258 else:
258 else:
259 raise JSONRPCError('repository `%s` does not exist' % (repoid))
259 raise JSONRPCError('repository `%s` does not exist' % (repoid))
260
260
261 if isinstance(userid, Optional):
261 if isinstance(userid, Optional):
262 userid = apiuser.user_id
262 userid = apiuser.user_id
263
263
264 user = get_user_or_error(userid)
264 user = get_user_or_error(userid)
265
265
266 if isinstance(locked, Optional):
266 if isinstance(locked, Optional):
267 lockobj = Repository.getlock(repo)
267 lockobj = Repository.getlock(repo)
268
268
269 if lockobj[0] is None:
269 if lockobj[0] is None:
270 _d = {
270 _d = {
271 'repo': repo.repo_name,
271 'repo': repo.repo_name,
272 'locked': False,
272 'locked': False,
273 'locked_since': None,
273 'locked_since': None,
274 'locked_by': None,
274 'locked_by': None,
275 'msg': 'Repo `%s` not locked.' % repo.repo_name
275 'msg': 'Repo `%s` not locked.' % repo.repo_name
276 }
276 }
277 return _d
277 return _d
278 else:
278 else:
279 userid, time_ = lockobj
279 userid, time_ = lockobj
280 lock_user = get_user_or_error(userid)
280 lock_user = get_user_or_error(userid)
281 _d = {
281 _d = {
282 'repo': repo.repo_name,
282 'repo': repo.repo_name,
283 'locked': True,
283 'locked': True,
284 'locked_since': time_,
284 'locked_since': time_,
285 'locked_by': lock_user.username,
285 'locked_by': lock_user.username,
286 'msg': ('Repo `%s` locked by `%s`. '
286 'msg': ('Repo `%s` locked by `%s`. '
287 % (repo.repo_name,
287 % (repo.repo_name,
288 json.dumps(time_to_datetime(time_))))
288 json.dumps(time_to_datetime(time_))))
289 }
289 }
290 return _d
290 return _d
291
291
292 # force locked state through a flag
292 # force locked state through a flag
293 else:
293 else:
294 locked = str2bool(locked)
294 locked = str2bool(locked)
295 try:
295 try:
296 if locked:
296 if locked:
297 lock_time = time.time()
297 lock_time = time.time()
298 Repository.lock(repo, user.user_id, lock_time)
298 Repository.lock(repo, user.user_id, lock_time)
299 else:
299 else:
300 lock_time = None
300 lock_time = None
301 Repository.unlock(repo)
301 Repository.unlock(repo)
302 _d = {
302 _d = {
303 'repo': repo.repo_name,
303 'repo': repo.repo_name,
304 'locked': locked,
304 'locked': locked,
305 'locked_since': lock_time,
305 'locked_since': lock_time,
306 'locked_by': user.username,
306 'locked_by': user.username,
307 'msg': ('User `%s` set lock state for repo `%s` to `%s`'
307 'msg': ('User `%s` set lock state for repo `%s` to `%s`'
308 % (user.username, repo.repo_name, locked))
308 % (user.username, repo.repo_name, locked))
309 }
309 }
310 return _d
310 return _d
311 except Exception:
311 except Exception:
312 log.error(traceback.format_exc())
312 log.error(traceback.format_exc())
313 raise JSONRPCError(
313 raise JSONRPCError(
314 'Error occurred locking repository `%s`' % repo.repo_name
314 'Error occurred locking repository `%s`' % repo.repo_name
315 )
315 )
316
316
317 def get_locks(self, apiuser, userid=Optional(OAttr('apiuser'))):
317 def get_locks(self, apiuser, userid=Optional(OAttr('apiuser'))):
318 """
318 """
319 Get all locks for given userid, if
319 Get all locks for given userid, if
320 this command is runned by non-admin account userid is set to user
320 this command is runned by non-admin account userid is set to user
321 who is calling this method, thus returning locks for himself
321 who is calling this method, thus returning locks for himself
322
322
323 :param apiuser:
323 :param apiuser:
324 :param userid:
324 :param userid:
325 """
325 """
326 if HasPermissionAnyApi('hg.admin')(user=apiuser):
326 if HasPermissionAnyApi('hg.admin')(user=apiuser):
327 pass
327 pass
328 else:
328 else:
329 #make sure normal user does not pass someone else userid,
329 #make sure normal user does not pass someone else userid,
330 #he is not allowed to do that
330 #he is not allowed to do that
331 if not isinstance(userid, Optional) and userid != apiuser.user_id:
331 if not isinstance(userid, Optional) and userid != apiuser.user_id:
332 raise JSONRPCError(
332 raise JSONRPCError(
333 'userid is not the same as your user'
333 'userid is not the same as your user'
334 )
334 )
335 ret = []
335 ret = []
336 if isinstance(userid, Optional):
336 if isinstance(userid, Optional):
337 user = None
337 user = None
338 else:
338 else:
339 user = get_user_or_error(userid)
339 user = get_user_or_error(userid)
340
340
341 #show all locks
341 #show all locks
342 for r in Repository.getAll():
342 for r in Repository.getAll():
343 userid, time_ = r.locked
343 userid, time_ = r.locked
344 if time_:
344 if time_:
345 _api_data = r.get_api_data()
345 _api_data = r.get_api_data()
346 # if we use userfilter just show the locks for this user
346 # if we use userfilter just show the locks for this user
347 if user:
347 if user:
348 if safe_int(userid) == user.user_id:
348 if safe_int(userid) == user.user_id:
349 ret.append(_api_data)
349 ret.append(_api_data)
350 else:
350 else:
351 ret.append(_api_data)
351 ret.append(_api_data)
352
352
353 return ret
353 return ret
354
354
355 @HasPermissionAllDecorator('hg.admin')
355 @HasPermissionAllDecorator('hg.admin')
356 def show_ip(self, apiuser, userid):
356 def show_ip(self, apiuser, userid):
357 """
357 """
358 Shows IP address as seen from RhodeCode server, together with all
358 Shows IP address as seen from RhodeCode server, together with all
359 defined IP addresses for given user
359 defined IP addresses for given user
360
360
361 :param apiuser:
361 :param apiuser:
362 :param userid:
362 :param userid:
363 """
363 """
364 user = get_user_or_error(userid)
364 user = get_user_or_error(userid)
365 ips = UserIpMap.query().filter(UserIpMap.user == user).all()
365 ips = UserIpMap.query().filter(UserIpMap.user == user).all()
366 return dict(
366 return dict(
367 ip_addr_server=self.ip_addr,
367 ip_addr_server=self.ip_addr,
368 user_ips=ips
368 user_ips=ips
369 )
369 )
370
370
371 def get_user(self, apiuser, userid=Optional(OAttr('apiuser'))):
371 def get_user(self, apiuser, userid=Optional(OAttr('apiuser'))):
372 """"
372 """"
373 Get a user by username, or userid, if userid is given
373 Get a user by username, or userid, if userid is given
374
374
375 :param apiuser:
375 :param apiuser:
376 :param userid:
376 :param userid:
377 """
377 """
378 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
378 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
379 #make sure normal user does not pass someone else userid,
379 #make sure normal user does not pass someone else userid,
380 #he is not allowed to do that
380 #he is not allowed to do that
381 if not isinstance(userid, Optional) and userid != apiuser.user_id:
381 if not isinstance(userid, Optional) and userid != apiuser.user_id:
382 raise JSONRPCError(
382 raise JSONRPCError(
383 'userid is not the same as your user'
383 'userid is not the same as your user'
384 )
384 )
385
385
386 if isinstance(userid, Optional):
386 if isinstance(userid, Optional):
387 userid = apiuser.user_id
387 userid = apiuser.user_id
388
388
389 user = get_user_or_error(userid)
389 user = get_user_or_error(userid)
390 data = user.get_api_data()
390 data = user.get_api_data()
391 data['permissions'] = AuthUser(user_id=user.user_id).permissions
391 data['permissions'] = AuthUser(user_id=user.user_id).permissions
392 return data
392 return data
393
393
394 @HasPermissionAllDecorator('hg.admin')
394 @HasPermissionAllDecorator('hg.admin')
395 def get_users(self, apiuser):
395 def get_users(self, apiuser):
396 """"
396 """"
397 Get all users
397 Get all users
398
398
399 :param apiuser:
399 :param apiuser:
400 """
400 """
401
401
402 result = []
402 result = []
403 users_list = User.query().order_by(User.username)\
403 users_list = User.query().order_by(User.username)\
404 .filter(User.username != User.DEFAULT_USER)\
404 .filter(User.username != User.DEFAULT_USER)\
405 .all()
405 .all()
406 for user in users_list:
406 for user in users_list:
407 result.append(user.get_api_data())
407 result.append(user.get_api_data())
408 return result
408 return result
409
409
410 @HasPermissionAllDecorator('hg.admin')
410 @HasPermissionAllDecorator('hg.admin')
411 def create_user(self, apiuser, username, email, password=Optional(None),
411 def create_user(self, apiuser, username, email, password=Optional(None),
412 firstname=Optional(None), lastname=Optional(None),
412 firstname=Optional(None), lastname=Optional(None),
413 active=Optional(True), admin=Optional(False),
413 active=Optional(True), admin=Optional(False),
414 ldap_dn=Optional(None)):
414 ldap_dn=Optional(None)):
415 """
415 """
416 Create new user
416 Create new user
417
417
418 :param apiuser:
418 :param apiuser:
419 :param username:
419 :param username:
420 :param email:
420 :param email:
421 :param password:
421 :param password:
422 :param firstname:
422 :param firstname:
423 :param lastname:
423 :param lastname:
424 :param active:
424 :param active:
425 :param admin:
425 :param admin:
426 :param ldap_dn:
426 :param ldap_dn:
427 """
427 """
428
428
429 if UserModel().get_by_username(username):
429 if UserModel().get_by_username(username):
430 raise JSONRPCError("user `%s` already exist" % username)
430 raise JSONRPCError("user `%s` already exist" % username)
431
431
432 if UserModel().get_by_email(email, case_insensitive=True):
432 if UserModel().get_by_email(email, case_insensitive=True):
433 raise JSONRPCError("email `%s` already exist" % email)
433 raise JSONRPCError("email `%s` already exist" % email)
434
434
435 if Optional.extract(ldap_dn):
435 if Optional.extract(ldap_dn):
436 # generate temporary password if ldap_dn
436 # generate temporary password if ldap_dn
437 password = PasswordGenerator().gen_password(length=8)
437 password = PasswordGenerator().gen_password(length=8)
438
438
439 try:
439 try:
440 user = UserModel().create_or_update(
440 user = UserModel().create_or_update(
441 username=Optional.extract(username),
441 username=Optional.extract(username),
442 password=Optional.extract(password),
442 password=Optional.extract(password),
443 email=Optional.extract(email),
443 email=Optional.extract(email),
444 firstname=Optional.extract(firstname),
444 firstname=Optional.extract(firstname),
445 lastname=Optional.extract(lastname),
445 lastname=Optional.extract(lastname),
446 active=Optional.extract(active),
446 active=Optional.extract(active),
447 admin=Optional.extract(admin),
447 admin=Optional.extract(admin),
448 ldap_dn=Optional.extract(ldap_dn)
448 ldap_dn=Optional.extract(ldap_dn)
449 )
449 )
450 Session().commit()
450 Session().commit()
451 return dict(
451 return dict(
452 msg='created new user `%s`' % username,
452 msg='created new user `%s`' % username,
453 user=user.get_api_data()
453 user=user.get_api_data()
454 )
454 )
455 except Exception:
455 except Exception:
456 log.error(traceback.format_exc())
456 log.error(traceback.format_exc())
457 raise JSONRPCError('failed to create user `%s`' % username)
457 raise JSONRPCError('failed to create user `%s`' % username)
458
458
459 @HasPermissionAllDecorator('hg.admin')
459 @HasPermissionAllDecorator('hg.admin')
460 def update_user(self, apiuser, userid, username=Optional(None),
460 def update_user(self, apiuser, userid, username=Optional(None),
461 email=Optional(None), firstname=Optional(None),
461 email=Optional(None), firstname=Optional(None),
462 lastname=Optional(None), active=Optional(None),
462 lastname=Optional(None), active=Optional(None),
463 admin=Optional(None), ldap_dn=Optional(None),
463 admin=Optional(None), ldap_dn=Optional(None),
464 password=Optional(None)):
464 password=Optional(None)):
465 """
465 """
466 Updates given user
466 Updates given user
467
467
468 :param apiuser:
468 :param apiuser:
469 :param userid:
469 :param userid:
470 :param username:
470 :param username:
471 :param email:
471 :param email:
472 :param firstname:
472 :param firstname:
473 :param lastname:
473 :param lastname:
474 :param active:
474 :param active:
475 :param admin:
475 :param admin:
476 :param ldap_dn:
476 :param ldap_dn:
477 :param password:
477 :param password:
478 """
478 """
479
479
480 user = get_user_or_error(userid)
480 user = get_user_or_error(userid)
481
481
482 # call function and store only updated arguments
482 # call function and store only updated arguments
483 updates = {}
483 updates = {}
484
484
485 def store_update(attr, name):
485 def store_update(attr, name):
486 if not isinstance(attr, Optional):
486 if not isinstance(attr, Optional):
487 updates[name] = attr
487 updates[name] = attr
488
488
489 try:
489 try:
490
490
491 store_update(username, 'username')
491 store_update(username, 'username')
492 store_update(password, 'password')
492 store_update(password, 'password')
493 store_update(email, 'email')
493 store_update(email, 'email')
494 store_update(firstname, 'name')
494 store_update(firstname, 'name')
495 store_update(lastname, 'lastname')
495 store_update(lastname, 'lastname')
496 store_update(active, 'active')
496 store_update(active, 'active')
497 store_update(admin, 'admin')
497 store_update(admin, 'admin')
498 store_update(ldap_dn, 'ldap_dn')
498 store_update(ldap_dn, 'ldap_dn')
499
499
500 user = UserModel().update_user(user, **updates)
500 user = UserModel().update_user(user, **updates)
501 Session().commit()
501 Session().commit()
502 return dict(
502 return dict(
503 msg='updated user ID:%s %s' % (user.user_id, user.username),
503 msg='updated user ID:%s %s' % (user.user_id, user.username),
504 user=user.get_api_data()
504 user=user.get_api_data()
505 )
505 )
506 except DefaultUserException:
506 except DefaultUserException:
507 log.error(traceback.format_exc())
507 log.error(traceback.format_exc())
508 raise JSONRPCError('editing default user is forbidden')
508 raise JSONRPCError('editing default user is forbidden')
509 except Exception:
509 except Exception:
510 log.error(traceback.format_exc())
510 log.error(traceback.format_exc())
511 raise JSONRPCError('failed to update user `%s`' % userid)
511 raise JSONRPCError('failed to update user `%s`' % userid)
512
512
513 @HasPermissionAllDecorator('hg.admin')
513 @HasPermissionAllDecorator('hg.admin')
514 def delete_user(self, apiuser, userid):
514 def delete_user(self, apiuser, userid):
515 """"
515 """"
516 Deletes an user
516 Deletes an user
517
517
518 :param apiuser:
518 :param apiuser:
519 :param userid:
519 :param userid:
520 """
520 """
521 user = get_user_or_error(userid)
521 user = get_user_or_error(userid)
522
522
523 try:
523 try:
524 UserModel().delete(userid)
524 UserModel().delete(userid)
525 Session().commit()
525 Session().commit()
526 return dict(
526 return dict(
527 msg='deleted user ID:%s %s' % (user.user_id, user.username),
527 msg='deleted user ID:%s %s' % (user.user_id, user.username),
528 user=None
528 user=None
529 )
529 )
530 except Exception:
530 except Exception:
531 log.error(traceback.format_exc())
531 log.error(traceback.format_exc())
532 raise JSONRPCError('failed to delete ID:%s %s' % (user.user_id,
532 raise JSONRPCError('failed to delete ID:%s %s' % (user.user_id,
533 user.username))
533 user.username))
534
534
535 @HasPermissionAllDecorator('hg.admin')
535 @HasPermissionAllDecorator('hg.admin')
536 def get_users_group(self, apiuser, usersgroupid):
536 def get_users_group(self, apiuser, usersgroupid):
537 """"
537 """"
538 Get user group by name or id
538 Get user group by name or id
539
539
540 :param apiuser:
540 :param apiuser:
541 :param usersgroupid:
541 :param usersgroupid:
542 """
542 """
543 users_group = get_users_group_or_error(usersgroupid)
543 users_group = get_users_group_or_error(usersgroupid)
544
544
545 data = users_group.get_api_data()
545 data = users_group.get_api_data()
546
546
547 members = []
547 members = []
548 for user in users_group.members:
548 for user in users_group.members:
549 user = user.user
549 user = user.user
550 members.append(user.get_api_data())
550 members.append(user.get_api_data())
551 data['members'] = members
551 data['members'] = members
552 return data
552 return data
553
553
554 @HasPermissionAllDecorator('hg.admin')
554 @HasPermissionAllDecorator('hg.admin')
555 def get_users_groups(self, apiuser):
555 def get_users_groups(self, apiuser):
556 """"
556 """"
557 Get all user groups
557 Get all user groups
558
558
559 :param apiuser:
559 :param apiuser:
560 """
560 """
561
561
562 result = []
562 result = []
563 for users_group in UserGroupModel().get_all():
563 for users_group in UserGroupModel().get_all():
564 result.append(users_group.get_api_data())
564 result.append(users_group.get_api_data())
565 return result
565 return result
566
566
567 @HasPermissionAllDecorator('hg.admin')
567 @HasPermissionAllDecorator('hg.admin')
568 def create_users_group(self, apiuser, group_name,
568 def create_users_group(self, apiuser, group_name,
569 owner=Optional(OAttr('apiuser')),
569 owner=Optional(OAttr('apiuser')),
570 active=Optional(True)):
570 active=Optional(True)):
571 """
571 """
572 Creates an new usergroup
572 Creates an new usergroup
573
573
574 :param apiuser:
574 :param apiuser:
575 :param group_name:
575 :param group_name:
576 :param owner:
576 :param owner:
577 :param active:
577 :param active:
578 """
578 """
579
579
580 if UserGroupModel().get_by_name(group_name):
580 if UserGroupModel().get_by_name(group_name):
581 raise JSONRPCError("user group `%s` already exist" % group_name)
581 raise JSONRPCError("user group `%s` already exist" % group_name)
582
582
583 try:
583 try:
584 if isinstance(owner, Optional):
584 if isinstance(owner, Optional):
585 owner = apiuser.user_id
585 owner = apiuser.user_id
586
586
587 owner = get_user_or_error(owner)
587 owner = get_user_or_error(owner)
588 active = Optional.extract(active)
588 active = Optional.extract(active)
589 ug = UserGroupModel().create(name=group_name,
589 ug = UserGroupModel().create(name=group_name,
590 owner=owner,
590 owner=owner,
591 active=active)
591 active=active)
592 Session().commit()
592 Session().commit()
593 return dict(
593 return dict(
594 msg='created new user group `%s`' % group_name,
594 msg='created new user group `%s`' % group_name,
595 users_group=ug.get_api_data()
595 users_group=ug.get_api_data()
596 )
596 )
597 except Exception:
597 except Exception:
598 log.error(traceback.format_exc())
598 log.error(traceback.format_exc())
599 raise JSONRPCError('failed to create group `%s`' % group_name)
599 raise JSONRPCError('failed to create group `%s`' % group_name)
600
600
601 @HasPermissionAllDecorator('hg.admin')
601 @HasPermissionAllDecorator('hg.admin')
602 def add_user_to_users_group(self, apiuser, usersgroupid, userid):
602 def add_user_to_users_group(self, apiuser, usersgroupid, userid):
603 """"
603 """"
604 Add a user to a user group
604 Add a user to a user group
605
605
606 :param apiuser:
606 :param apiuser:
607 :param usersgroupid:
607 :param usersgroupid:
608 :param userid:
608 :param userid:
609 """
609 """
610 user = get_user_or_error(userid)
610 user = get_user_or_error(userid)
611 users_group = get_users_group_or_error(usersgroupid)
611 users_group = get_users_group_or_error(usersgroupid)
612
612
613 try:
613 try:
614 ugm = UserGroupModel().add_user_to_group(users_group, user)
614 ugm = UserGroupModel().add_user_to_group(users_group, user)
615 success = True if ugm != True else False
615 success = True if ugm != True else False
616 msg = 'added member `%s` to user group `%s`' % (
616 msg = 'added member `%s` to user group `%s`' % (
617 user.username, users_group.users_group_name
617 user.username, users_group.users_group_name
618 )
618 )
619 msg = msg if success else 'User is already in that group'
619 msg = msg if success else 'User is already in that group'
620 Session().commit()
620 Session().commit()
621
621
622 return dict(
622 return dict(
623 success=success,
623 success=success,
624 msg=msg
624 msg=msg
625 )
625 )
626 except Exception:
626 except Exception:
627 log.error(traceback.format_exc())
627 log.error(traceback.format_exc())
628 raise JSONRPCError(
628 raise JSONRPCError(
629 'failed to add member to user group `%s`' % (
629 'failed to add member to user group `%s`' % (
630 users_group.users_group_name
630 users_group.users_group_name
631 )
631 )
632 )
632 )
633
633
634 @HasPermissionAllDecorator('hg.admin')
634 @HasPermissionAllDecorator('hg.admin')
635 def remove_user_from_users_group(self, apiuser, usersgroupid, userid):
635 def remove_user_from_users_group(self, apiuser, usersgroupid, userid):
636 """
636 """
637 Remove user from a group
637 Remove user from a group
638
638
639 :param apiuser:
639 :param apiuser:
640 :param usersgroupid:
640 :param usersgroupid:
641 :param userid:
641 :param userid:
642 """
642 """
643 user = get_user_or_error(userid)
643 user = get_user_or_error(userid)
644 users_group = get_users_group_or_error(usersgroupid)
644 users_group = get_users_group_or_error(usersgroupid)
645
645
646 try:
646 try:
647 success = UserGroupModel().remove_user_from_group(users_group,
647 success = UserGroupModel().remove_user_from_group(users_group,
648 user)
648 user)
649 msg = 'removed member `%s` from user group `%s`' % (
649 msg = 'removed member `%s` from user group `%s`' % (
650 user.username, users_group.users_group_name
650 user.username, users_group.users_group_name
651 )
651 )
652 msg = msg if success else "User wasn't in group"
652 msg = msg if success else "User wasn't in group"
653 Session().commit()
653 Session().commit()
654 return dict(success=success, msg=msg)
654 return dict(success=success, msg=msg)
655 except Exception:
655 except Exception:
656 log.error(traceback.format_exc())
656 log.error(traceback.format_exc())
657 raise JSONRPCError(
657 raise JSONRPCError(
658 'failed to remove member from user group `%s`' % (
658 'failed to remove member from user group `%s`' % (
659 users_group.users_group_name
659 users_group.users_group_name
660 )
660 )
661 )
661 )
662
662
663 def get_repo(self, apiuser, repoid):
663 def get_repo(self, apiuser, repoid):
664 """"
664 """"
665 Get repository by name
665 Get repository by name
666
666
667 :param apiuser:
667 :param apiuser:
668 :param repoid:
668 :param repoid:
669 """
669 """
670 repo = get_repo_or_error(repoid)
670 repo = get_repo_or_error(repoid)
671
671
672 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
672 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
673 # check if we have admin permission for this repo !
673 # check if we have admin permission for this repo !
674 if HasRepoPermissionAnyApi('repository.admin')(user=apiuser,
674 if HasRepoPermissionAnyApi('repository.admin')(user=apiuser,
675 repo_name=repo.repo_name) is False:
675 repo_name=repo.repo_name) is False:
676 raise JSONRPCError('repository `%s` does not exist' % (repoid))
676 raise JSONRPCError('repository `%s` does not exist' % (repoid))
677
677
678 members = []
678 members = []
679 followers = []
679 followers = []
680 for user in repo.repo_to_perm:
680 for user in repo.repo_to_perm:
681 perm = user.permission.permission_name
681 perm = user.permission.permission_name
682 user = user.user
682 user = user.user
683 user_data = user.get_api_data()
683 user_data = user.get_api_data()
684 user_data['type'] = "user"
684 user_data['type'] = "user"
685 user_data['permission'] = perm
685 user_data['permission'] = perm
686 members.append(user_data)
686 members.append(user_data)
687
687
688 for users_group in repo.users_group_to_perm:
688 for users_group in repo.users_group_to_perm:
689 perm = users_group.permission.permission_name
689 perm = users_group.permission.permission_name
690 users_group = users_group.users_group
690 users_group = users_group.users_group
691 users_group_data = users_group.get_api_data()
691 users_group_data = users_group.get_api_data()
692 users_group_data['type'] = "users_group"
692 users_group_data['type'] = "users_group"
693 users_group_data['permission'] = perm
693 users_group_data['permission'] = perm
694 members.append(users_group_data)
694 members.append(users_group_data)
695
695
696 for user in repo.followers:
696 for user in repo.followers:
697 followers.append(user.user.get_api_data())
697 followers.append(user.user.get_api_data())
698
698
699 data = repo.get_api_data()
699 data = repo.get_api_data()
700 data['members'] = members
700 data['members'] = members
701 data['followers'] = followers
701 data['followers'] = followers
702 return data
702 return data
703
703
704 def get_repos(self, apiuser):
704 def get_repos(self, apiuser):
705 """"
705 """"
706 Get all repositories
706 Get all repositories
707
707
708 :param apiuser:
708 :param apiuser:
709 """
709 """
710 result = []
710 result = []
711 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
711 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
712 repos = RepoModel().get_all_user_repos(user=apiuser)
712 repos = RepoModel().get_all_user_repos(user=apiuser)
713 else:
713 else:
714 repos = RepoModel().get_all()
714 repos = RepoModel().get_all()
715
715
716 for repo in repos:
716 for repo in repos:
717 result.append(repo.get_api_data())
717 result.append(repo.get_api_data())
718 return result
718 return result
719
719
720 @HasPermissionAllDecorator('hg.admin')
720 @HasPermissionAllDecorator('hg.admin')
721 def get_repo_nodes(self, apiuser, repoid, revision, root_path,
721 def get_repo_nodes(self, apiuser, repoid, revision, root_path,
722 ret_type='all'):
722 ret_type='all'):
723 """
723 """
724 returns a list of nodes and it's children
724 returns a list of nodes and it's children
725 for a given path at given revision. It's possible to specify ret_type
725 for a given path at given revision. It's possible to specify ret_type
726 to show only files or dirs
726 to show only files or dirs
727
727
728 :param apiuser:
728 :param apiuser:
729 :param repoid: name or id of repository
729 :param repoid: name or id of repository
730 :param revision: revision for which listing should be done
730 :param revision: revision for which listing should be done
731 :param root_path: path from which start displaying
731 :param root_path: path from which start displaying
732 :param ret_type: return type 'all|files|dirs' nodes
732 :param ret_type: return type 'all|files|dirs' nodes
733 """
733 """
734 repo = get_repo_or_error(repoid)
734 repo = get_repo_or_error(repoid)
735 try:
735 try:
736 _d, _f = ScmModel().get_nodes(repo, revision, root_path,
736 _d, _f = ScmModel().get_nodes(repo, revision, root_path,
737 flat=False)
737 flat=False)
738 _map = {
738 _map = {
739 'all': _d + _f,
739 'all': _d + _f,
740 'files': _f,
740 'files': _f,
741 'dirs': _d,
741 'dirs': _d,
742 }
742 }
743 return _map[ret_type]
743 return _map[ret_type]
744 except KeyError:
744 except KeyError:
745 raise JSONRPCError('ret_type must be one of %s' % _map.keys())
745 raise JSONRPCError('ret_type must be one of %s' % _map.keys())
746 except Exception:
746 except Exception:
747 log.error(traceback.format_exc())
747 log.error(traceback.format_exc())
748 raise JSONRPCError(
748 raise JSONRPCError(
749 'failed to get repo: `%s` nodes' % repo.repo_name
749 'failed to get repo: `%s` nodes' % repo.repo_name
750 )
750 )
751
751
752 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
752 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
753 def create_repo(self, apiuser, repo_name, owner=Optional(OAttr('apiuser')),
753 def create_repo(self, apiuser, repo_name, owner=Optional(OAttr('apiuser')),
754 repo_type=Optional('hg'),
754 repo_type=Optional('hg'),
755 description=Optional(''), private=Optional(False),
755 description=Optional(''), private=Optional(False),
756 clone_uri=Optional(None), landing_rev=Optional('tip'),
756 clone_uri=Optional(None), landing_rev=Optional('tip'),
757 enable_statistics=Optional(False),
757 enable_statistics=Optional(False),
758 enable_locking=Optional(False),
758 enable_locking=Optional(False),
759 enable_downloads=Optional(False)):
759 enable_downloads=Optional(False)):
760 """
760 """
761 Create repository, if clone_url is given it makes a remote clone
761 Create repository, if clone_url is given it makes a remote clone
762 if repo_name is within a group name the groups will be created
762 if repo_name is within a group name the groups will be created
763 automatically if they aren't present
763 automatically if they aren't present
764
764
765 :param apiuser:
765 :param apiuser:
766 :param repo_name:
766 :param repo_name:
767 :param onwer:
767 :param onwer:
768 :param repo_type:
768 :param repo_type:
769 :param description:
769 :param description:
770 :param private:
770 :param private:
771 :param clone_uri:
771 :param clone_uri:
772 :param landing_rev:
772 :param landing_rev:
773 """
773 """
774 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
774 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
775 if not isinstance(owner, Optional):
775 if not isinstance(owner, Optional):
776 #forbid setting owner for non-admins
776 #forbid setting owner for non-admins
777 raise JSONRPCError(
777 raise JSONRPCError(
778 'Only RhodeCode admin can specify `owner` param'
778 'Only RhodeCode admin can specify `owner` param'
779 )
779 )
780 if isinstance(owner, Optional):
780 if isinstance(owner, Optional):
781 owner = apiuser.user_id
781 owner = apiuser.user_id
782
782
783 owner = get_user_or_error(owner)
783 owner = get_user_or_error(owner)
784
784
785 if RepoModel().get_by_repo_name(repo_name):
785 if RepoModel().get_by_repo_name(repo_name):
786 raise JSONRPCError("repo `%s` already exist" % repo_name)
786 raise JSONRPCError("repo `%s` already exist" % repo_name)
787
787
788 defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
788 defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
789 if isinstance(private, Optional):
789 if isinstance(private, Optional):
790 private = defs.get('repo_private') or Optional.extract(private)
790 private = defs.get('repo_private') or Optional.extract(private)
791 if isinstance(repo_type, Optional):
791 if isinstance(repo_type, Optional):
792 repo_type = defs.get('repo_type')
792 repo_type = defs.get('repo_type')
793 if isinstance(enable_statistics, Optional):
793 if isinstance(enable_statistics, Optional):
794 enable_statistics = defs.get('repo_enable_statistics')
794 enable_statistics = defs.get('repo_enable_statistics')
795 if isinstance(enable_locking, Optional):
795 if isinstance(enable_locking, Optional):
796 enable_locking = defs.get('repo_enable_locking')
796 enable_locking = defs.get('repo_enable_locking')
797 if isinstance(enable_downloads, Optional):
797 if isinstance(enable_downloads, Optional):
798 enable_downloads = defs.get('repo_enable_downloads')
798 enable_downloads = defs.get('repo_enable_downloads')
799
799
800 clone_uri = Optional.extract(clone_uri)
800 clone_uri = Optional.extract(clone_uri)
801 description = Optional.extract(description)
801 description = Optional.extract(description)
802 landing_rev = Optional.extract(landing_rev)
802 landing_rev = Optional.extract(landing_rev)
803
803
804 try:
804 try:
805 # create structure of groups and return the last group
805 # create structure of groups and return the last group
806 group = map_groups(repo_name)
806 group = map_groups(repo_name)
807
807
808 repo = RepoModel().create_repo(
808 repo = RepoModel().create_repo(
809 repo_name=repo_name,
809 repo_name=repo_name,
810 repo_type=repo_type,
810 repo_type=repo_type,
811 description=description,
811 description=description,
812 owner=owner,
812 owner=owner,
813 private=private,
813 private=private,
814 clone_uri=clone_uri,
814 clone_uri=clone_uri,
815 repos_group=group,
815 repos_group=group,
816 landing_rev=landing_rev,
816 landing_rev=landing_rev,
817 enable_statistics=enable_statistics,
817 enable_statistics=enable_statistics,
818 enable_downloads=enable_downloads,
818 enable_downloads=enable_downloads,
819 enable_locking=enable_locking
819 enable_locking=enable_locking
820 )
820 )
821
821
822 Session().commit()
822 Session().commit()
823 return dict(
823 return dict(
824 msg="Created new repository `%s`" % (repo.repo_name),
824 msg="Created new repository `%s`" % (repo.repo_name),
825 repo=repo.get_api_data()
825 repo=repo.get_api_data()
826 )
826 )
827 except Exception:
827 except Exception:
828 log.error(traceback.format_exc())
828 log.error(traceback.format_exc())
829 raise JSONRPCError('failed to create repository `%s`' % repo_name)
829 raise JSONRPCError('failed to create repository `%s`' % repo_name)
830
830
831 @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
831 @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
832 def fork_repo(self, apiuser, repoid, fork_name, owner=Optional(OAttr('apiuser')),
832 def fork_repo(self, apiuser, repoid, fork_name, owner=Optional(OAttr('apiuser')),
833 description=Optional(''), copy_permissions=Optional(False),
833 description=Optional(''), copy_permissions=Optional(False),
834 private=Optional(False), landing_rev=Optional('tip')):
834 private=Optional(False), landing_rev=Optional('tip')):
835 repo = get_repo_or_error(repoid)
835 repo = get_repo_or_error(repoid)
836 repo_name = repo.repo_name
836 repo_name = repo.repo_name
837
837
838 _repo = RepoModel().get_by_repo_name(fork_name)
838 _repo = RepoModel().get_by_repo_name(fork_name)
839 if _repo:
839 if _repo:
840 type_ = 'fork' if _repo.fork else 'repo'
840 type_ = 'fork' if _repo.fork else 'repo'
841 raise JSONRPCError("%s `%s` already exist" % (type_, fork_name))
841 raise JSONRPCError("%s `%s` already exist" % (type_, fork_name))
842
842
843 if HasPermissionAnyApi('hg.admin')(user=apiuser):
843 if HasPermissionAnyApi('hg.admin')(user=apiuser):
844 pass
844 pass
845 elif HasRepoPermissionAnyApi('repository.admin',
845 elif HasRepoPermissionAnyApi('repository.admin',
846 'repository.write',
846 'repository.write',
847 'repository.read')(user=apiuser,
847 'repository.read')(user=apiuser,
848 repo_name=repo.repo_name):
848 repo_name=repo.repo_name):
849 if not isinstance(owner, Optional):
849 if not isinstance(owner, Optional):
850 #forbid setting owner for non-admins
850 #forbid setting owner for non-admins
851 raise JSONRPCError(
851 raise JSONRPCError(
852 'Only RhodeCode admin can specify `owner` param'
852 'Only RhodeCode admin can specify `owner` param'
853 )
853 )
854 else:
854 else:
855 raise JSONRPCError('repository `%s` does not exist' % (repoid))
855 raise JSONRPCError('repository `%s` does not exist' % (repoid))
856
856
857 if isinstance(owner, Optional):
857 if isinstance(owner, Optional):
858 owner = apiuser.user_id
858 owner = apiuser.user_id
859
859
860 owner = get_user_or_error(owner)
860 owner = get_user_or_error(owner)
861
861
862 try:
862 try:
863 # create structure of groups and return the last group
863 # create structure of groups and return the last group
864 group = map_groups(fork_name)
864 group = map_groups(fork_name)
865
865
866 form_data = dict(
866 form_data = dict(
867 repo_name=fork_name,
867 repo_name=fork_name,
868 repo_name_full=fork_name,
868 repo_name_full=fork_name,
869 repo_group=group,
869 repo_group=group,
870 repo_type=repo.repo_type,
870 repo_type=repo.repo_type,
871 description=Optional.extract(description),
871 description=Optional.extract(description),
872 private=Optional.extract(private),
872 private=Optional.extract(private),
873 copy_permissions=Optional.extract(copy_permissions),
873 copy_permissions=Optional.extract(copy_permissions),
874 landing_rev=Optional.extract(landing_rev),
874 landing_rev=Optional.extract(landing_rev),
875 update_after_clone=False,
875 update_after_clone=False,
876 fork_parent_id=repo.repo_id,
876 fork_parent_id=repo.repo_id,
877 )
877 )
878 RepoModel().create_fork(form_data, cur_user=owner)
878 RepoModel().create_fork(form_data, cur_user=owner)
879 return dict(
879 return dict(
880 msg='Created fork of `%s` as `%s`' % (repo.repo_name,
880 msg='Created fork of `%s` as `%s`' % (repo.repo_name,
881 fork_name),
881 fork_name),
882 success=True # cannot return the repo data here since fork
882 success=True # cannot return the repo data here since fork
883 # cann be done async
883 # cann be done async
884 )
884 )
885 except Exception:
885 except Exception:
886 log.error(traceback.format_exc())
886 log.error(traceback.format_exc())
887 raise JSONRPCError(
887 raise JSONRPCError(
888 'failed to fork repository `%s` as `%s`' % (repo_name,
888 'failed to fork repository `%s` as `%s`' % (repo_name,
889 fork_name)
889 fork_name)
890 )
890 )
891
891
892 # perms handled inside
892 # perms handled inside
893 def delete_repo(self, apiuser, repoid, forks=Optional(None)):
893 def delete_repo(self, apiuser, repoid, forks=Optional(None)):
894 """
894 """
895 Deletes a given repository
895 Deletes a given repository
896
896
897 :param apiuser:
897 :param apiuser:
898 :param repoid:
898 :param repoid:
899 :param forks: detach or delete, what do do with attached forks for repo
899 :param forks: detach or delete, what do do with attached forks for repo
900 """
900 """
901 repo = get_repo_or_error(repoid)
901 repo = get_repo_or_error(repoid)
902
902
903 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
903 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
904 # check if we have admin permission for this repo !
904 # check if we have admin permission for this repo !
905 if HasRepoPermissionAnyApi('repository.admin')(user=apiuser,
905 if HasRepoPermissionAnyApi('repository.admin')(user=apiuser,
906 repo_name=repo.repo_name) is False:
906 repo_name=repo.repo_name) is False:
907 raise JSONRPCError('repository `%s` does not exist' % (repoid))
907 raise JSONRPCError('repository `%s` does not exist' % (repoid))
908
908
909 try:
909 try:
910 handle_forks = Optional.extract(forks)
910 handle_forks = Optional.extract(forks)
911 _forks_msg = ''
911 _forks_msg = ''
912 _forks = [f for f in repo.forks]
912 _forks = [f for f in repo.forks]
913 if handle_forks == 'detach':
913 if handle_forks == 'detach':
914 _forks_msg = ' ' + _('Detached %s forks') % len(_forks)
914 _forks_msg = ' ' + 'Detached %s forks' % len(_forks)
915 elif handle_forks == 'delete':
915 elif handle_forks == 'delete':
916 _forks_msg = ' ' + _('Deleted %s forks') % len(_forks)
916 _forks_msg = ' ' + 'Deleted %s forks' % len(_forks)
917 elif _forks:
917 elif _forks:
918 raise JSONRPCError(
918 raise JSONRPCError(
919 'Cannot delete `%s` it still contains attached forks'
919 'Cannot delete `%s` it still contains attached forks'
920 % repo.repo_name
920 % repo.repo_name
921 )
921 )
922
922
923 RepoModel().delete(repo, forks=forks)
923 RepoModel().delete(repo, forks=forks)
924 Session().commit()
924 Session().commit()
925 return dict(
925 return dict(
926 msg='Deleted repository `%s`%s' % (repo.repo_name, _forks_msg),
926 msg='Deleted repository `%s`%s' % (repo.repo_name, _forks_msg),
927 success=True
927 success=True
928 )
928 )
929 except Exception:
929 except Exception:
930 log.error(traceback.format_exc())
930 log.error(traceback.format_exc())
931 raise JSONRPCError(
931 raise JSONRPCError(
932 'failed to delete repository `%s`' % repo.repo_name
932 'failed to delete repository `%s`' % repo.repo_name
933 )
933 )
934
934
935 @HasPermissionAllDecorator('hg.admin')
935 @HasPermissionAllDecorator('hg.admin')
936 def grant_user_permission(self, apiuser, repoid, userid, perm):
936 def grant_user_permission(self, apiuser, repoid, userid, perm):
937 """
937 """
938 Grant permission for user on given repository, or update existing one
938 Grant permission for user on given repository, or update existing one
939 if found
939 if found
940
940
941 :param repoid:
941 :param repoid:
942 :param userid:
942 :param userid:
943 :param perm:
943 :param perm:
944 """
944 """
945 repo = get_repo_or_error(repoid)
945 repo = get_repo_or_error(repoid)
946 user = get_user_or_error(userid)
946 user = get_user_or_error(userid)
947 perm = get_perm_or_error(perm)
947 perm = get_perm_or_error(perm)
948
948
949 try:
949 try:
950
950
951 RepoModel().grant_user_permission(repo=repo, user=user, perm=perm)
951 RepoModel().grant_user_permission(repo=repo, user=user, perm=perm)
952
952
953 Session().commit()
953 Session().commit()
954 return dict(
954 return dict(
955 msg='Granted perm: `%s` for user: `%s` in repo: `%s`' % (
955 msg='Granted perm: `%s` for user: `%s` in repo: `%s`' % (
956 perm.permission_name, user.username, repo.repo_name
956 perm.permission_name, user.username, repo.repo_name
957 ),
957 ),
958 success=True
958 success=True
959 )
959 )
960 except Exception:
960 except Exception:
961 log.error(traceback.format_exc())
961 log.error(traceback.format_exc())
962 raise JSONRPCError(
962 raise JSONRPCError(
963 'failed to edit permission for user: `%s` in repo: `%s`' % (
963 'failed to edit permission for user: `%s` in repo: `%s`' % (
964 userid, repoid
964 userid, repoid
965 )
965 )
966 )
966 )
967
967
968 @HasPermissionAllDecorator('hg.admin')
968 @HasPermissionAllDecorator('hg.admin')
969 def revoke_user_permission(self, apiuser, repoid, userid):
969 def revoke_user_permission(self, apiuser, repoid, userid):
970 """
970 """
971 Revoke permission for user on given repository
971 Revoke permission for user on given repository
972
972
973 :param apiuser:
973 :param apiuser:
974 :param repoid:
974 :param repoid:
975 :param userid:
975 :param userid:
976 """
976 """
977
977
978 repo = get_repo_or_error(repoid)
978 repo = get_repo_or_error(repoid)
979 user = get_user_or_error(userid)
979 user = get_user_or_error(userid)
980 try:
980 try:
981
981
982 RepoModel().revoke_user_permission(repo=repo, user=user)
982 RepoModel().revoke_user_permission(repo=repo, user=user)
983
983
984 Session().commit()
984 Session().commit()
985 return dict(
985 return dict(
986 msg='Revoked perm for user: `%s` in repo: `%s`' % (
986 msg='Revoked perm for user: `%s` in repo: `%s`' % (
987 user.username, repo.repo_name
987 user.username, repo.repo_name
988 ),
988 ),
989 success=True
989 success=True
990 )
990 )
991 except Exception:
991 except Exception:
992 log.error(traceback.format_exc())
992 log.error(traceback.format_exc())
993 raise JSONRPCError(
993 raise JSONRPCError(
994 'failed to edit permission for user: `%s` in repo: `%s`' % (
994 'failed to edit permission for user: `%s` in repo: `%s`' % (
995 userid, repoid
995 userid, repoid
996 )
996 )
997 )
997 )
998
998
999 @HasPermissionAllDecorator('hg.admin')
999 @HasPermissionAllDecorator('hg.admin')
1000 def grant_users_group_permission(self, apiuser, repoid, usersgroupid,
1000 def grant_users_group_permission(self, apiuser, repoid, usersgroupid,
1001 perm):
1001 perm):
1002 """
1002 """
1003 Grant permission for user group on given repository, or update
1003 Grant permission for user group on given repository, or update
1004 existing one if found
1004 existing one if found
1005
1005
1006 :param apiuser:
1006 :param apiuser:
1007 :param repoid:
1007 :param repoid:
1008 :param usersgroupid:
1008 :param usersgroupid:
1009 :param perm:
1009 :param perm:
1010 """
1010 """
1011 repo = get_repo_or_error(repoid)
1011 repo = get_repo_or_error(repoid)
1012 perm = get_perm_or_error(perm)
1012 perm = get_perm_or_error(perm)
1013 users_group = get_users_group_or_error(usersgroupid)
1013 users_group = get_users_group_or_error(usersgroupid)
1014
1014
1015 try:
1015 try:
1016 RepoModel().grant_users_group_permission(repo=repo,
1016 RepoModel().grant_users_group_permission(repo=repo,
1017 group_name=users_group,
1017 group_name=users_group,
1018 perm=perm)
1018 perm=perm)
1019
1019
1020 Session().commit()
1020 Session().commit()
1021 return dict(
1021 return dict(
1022 msg='Granted perm: `%s` for user group: `%s` in '
1022 msg='Granted perm: `%s` for user group: `%s` in '
1023 'repo: `%s`' % (
1023 'repo: `%s`' % (
1024 perm.permission_name, users_group.users_group_name,
1024 perm.permission_name, users_group.users_group_name,
1025 repo.repo_name
1025 repo.repo_name
1026 ),
1026 ),
1027 success=True
1027 success=True
1028 )
1028 )
1029 except Exception:
1029 except Exception:
1030 log.error(traceback.format_exc())
1030 log.error(traceback.format_exc())
1031 raise JSONRPCError(
1031 raise JSONRPCError(
1032 'failed to edit permission for user group: `%s` in '
1032 'failed to edit permission for user group: `%s` in '
1033 'repo: `%s`' % (
1033 'repo: `%s`' % (
1034 usersgroupid, repo.repo_name
1034 usersgroupid, repo.repo_name
1035 )
1035 )
1036 )
1036 )
1037
1037
1038 @HasPermissionAllDecorator('hg.admin')
1038 @HasPermissionAllDecorator('hg.admin')
1039 def revoke_users_group_permission(self, apiuser, repoid, usersgroupid):
1039 def revoke_users_group_permission(self, apiuser, repoid, usersgroupid):
1040 """
1040 """
1041 Revoke permission for user group on given repository
1041 Revoke permission for user group on given repository
1042
1042
1043 :param apiuser:
1043 :param apiuser:
1044 :param repoid:
1044 :param repoid:
1045 :param usersgroupid:
1045 :param usersgroupid:
1046 """
1046 """
1047 repo = get_repo_or_error(repoid)
1047 repo = get_repo_or_error(repoid)
1048 users_group = get_users_group_or_error(usersgroupid)
1048 users_group = get_users_group_or_error(usersgroupid)
1049
1049
1050 try:
1050 try:
1051 RepoModel().revoke_users_group_permission(repo=repo,
1051 RepoModel().revoke_users_group_permission(repo=repo,
1052 group_name=users_group)
1052 group_name=users_group)
1053
1053
1054 Session().commit()
1054 Session().commit()
1055 return dict(
1055 return dict(
1056 msg='Revoked perm for user group: `%s` in repo: `%s`' % (
1056 msg='Revoked perm for user group: `%s` in repo: `%s`' % (
1057 users_group.users_group_name, repo.repo_name
1057 users_group.users_group_name, repo.repo_name
1058 ),
1058 ),
1059 success=True
1059 success=True
1060 )
1060 )
1061 except Exception:
1061 except Exception:
1062 log.error(traceback.format_exc())
1062 log.error(traceback.format_exc())
1063 raise JSONRPCError(
1063 raise JSONRPCError(
1064 'failed to edit permission for user group: `%s` in '
1064 'failed to edit permission for user group: `%s` in '
1065 'repo: `%s`' % (
1065 'repo: `%s`' % (
1066 users_group.users_group_name, repo.repo_name
1066 users_group.users_group_name, repo.repo_name
1067 )
1067 )
1068 )
1068 )
1069
1069
1070 def create_gist(self, apiuser, files, owner=Optional(OAttr('apiuser')),
1070 def create_gist(self, apiuser, files, owner=Optional(OAttr('apiuser')),
1071 gist_type=Optional(Gist.GIST_PUBLIC),
1071 gist_type=Optional(Gist.GIST_PUBLIC),
1072 gist_lifetime=Optional(-1),
1072 gist_lifetime=Optional(-1),
1073 gist_description=Optional('')):
1073 gist_description=Optional('')):
1074
1074
1075 try:
1075 try:
1076 if isinstance(owner, Optional):
1076 if isinstance(owner, Optional):
1077 owner = apiuser.user_id
1077 owner = apiuser.user_id
1078
1078
1079 owner = get_user_or_error(owner)
1079 owner = get_user_or_error(owner)
1080 description = Optional.extract(gist_description)
1080 description = Optional.extract(gist_description)
1081 gist_type = Optional.extract(gist_type)
1081 gist_type = Optional.extract(gist_type)
1082 gist_lifetime = Optional.extract(gist_lifetime)
1082 gist_lifetime = Optional.extract(gist_lifetime)
1083
1083
1084 # files: {
1084 # files: {
1085 # 'filename': {'content':'...', 'lexer': null},
1085 # 'filename': {'content':'...', 'lexer': null},
1086 # 'filename2': {'content':'...', 'lexer': null}
1086 # 'filename2': {'content':'...', 'lexer': null}
1087 #}
1087 #}
1088 gist = GistModel().create(description=description,
1088 gist = GistModel().create(description=description,
1089 owner=owner,
1089 owner=owner,
1090 gist_mapping=files,
1090 gist_mapping=files,
1091 gist_type=gist_type,
1091 gist_type=gist_type,
1092 lifetime=gist_lifetime)
1092 lifetime=gist_lifetime)
1093 Session().commit()
1093 Session().commit()
1094 return dict(
1094 return dict(
1095 msg='created new gist',
1095 msg='created new gist',
1096 gist_url=gist.gist_url(),
1096 gist_url=gist.gist_url(),
1097 gist_id=gist.gist_access_id,
1097 gist_id=gist.gist_access_id,
1098 gist_type=gist.gist_type,
1098 gist_type=gist.gist_type,
1099 files=files.keys()
1099 files=files.keys()
1100 )
1100 )
1101 except Exception:
1101 except Exception:
1102 log.error(traceback.format_exc())
1102 log.error(traceback.format_exc())
1103 raise JSONRPCError('failed to create gist')
1103 raise JSONRPCError('failed to create gist')
1104
1104
1105 def update_gist(self, apiuser):
1105 def update_gist(self, apiuser):
1106 pass
1106 pass
1107
1107
1108 def delete_gist(self, apiuser):
1108 def delete_gist(self, apiuser):
1109 pass
1109 pass
General Comments 0
You need to be logged in to leave comments. Login now