Mercurial > kallithea
comparison rhodecode/controllers/api/api.py @ 4116:ffd45b185016 rhodecode-2.2.5-gpl
Imported some of the GPLv3'd changes from RhodeCode v2.2.5.
This imports changes between changesets 21af6c4eab3d and 6177597791c2 in
RhodeCode's original repository, including only changes to Python files and HTML.
RhodeCode clearly licensed its changes to these files under GPLv3
in their /LICENSE file, which states the following:
The Python code and integrated HTML are licensed under the GPLv3 license.
(See:
https://code.rhodecode.com/rhodecode/files/v2.2.5/LICENSE
or
http://web.archive.org/web/20140512193334/https://code.rhodecode.com/rhodecode/files/f3b123159901f15426d18e3dc395e8369f70ebe0/LICENSE
for an online copy of that LICENSE file)
Conservancy reviewed these changes and confirmed that they can be licensed as
a whole to the Kallithea project under GPLv3-only.
While some of the contents committed herein are clearly licensed
GPLv3-or-later, on the whole we must assume the are GPLv3-only, since the
statement above from RhodeCode indicates that they intend GPLv3-only as their
license, per GPLv3ยง14 and other relevant sections of GPLv3.
author | Bradley M. Kuhn <bkuhn@sfconservancy.org> |
---|---|
date | Wed, 02 Jul 2014 19:03:13 -0400 |
parents | 5293d4bbb1ea |
children | 7e5f8c12a3fc |
comparison
equal
deleted
inserted
replaced
4115:8b7294a804a0 | 4116:ffd45b185016 |
---|---|
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 """ | 2 # This program is free software: you can redistribute it and/or modify |
3 rhodecode.controllers.api | 3 # it under the terms of the GNU General Public License as published by |
4 ~~~~~~~~~~~~~~~~~~~~~~~~~ | 4 # the Free Software Foundation, either version 3 of the License, or |
5 | 5 # (at your option) any later version. |
6 API controller for RhodeCode | |
7 | |
8 :created_on: Aug 20, 2011 | |
9 :author: marcink | |
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com> | |
11 :license: GPLv3, see COPYING for more details. | |
12 """ | |
13 # This program is free software; you can redistribute it and/or | |
14 # modify it under the terms of the GNU General Public License | |
15 # as published by the Free Software Foundation; version 2 | |
16 # of the License or (at your opinion) any later version of the license. | |
17 # | 6 # |
18 # This program is distributed in the hope that it will be useful, | 7 # This program is distributed in the hope that it will be useful, |
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 # GNU General Public License for more details. | 10 # GNU General Public License for more details. |
22 # | 11 # |
23 # You should have received a copy of the GNU General Public License | 12 # You should have received a copy of the GNU General Public License |
24 # along with this program; if not, write to the Free Software | 13 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | 14 """ |
26 # MA 02110-1301, USA. | 15 rhodecode.controllers.api |
16 ~~~~~~~~~~~~~~~~~~~~~~~~~ | |
17 | |
18 API controller for RhodeCode | |
19 | |
20 :created_on: Aug 20, 2011 | |
21 :author: marcink | |
22 :copyright: (c) 2013 RhodeCode GmbH. | |
23 :license: GPLv3, see LICENSE for more details. | |
24 """ | |
25 | |
27 | 26 |
28 import time | 27 import time |
29 import traceback | 28 import traceback |
30 import logging | 29 import logging |
30 from sqlalchemy import or_ | |
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 ( |
34 HasPermissionAllDecorator, HasPermissionAnyDecorator, \ | 34 PasswordGenerator, AuthUser, HasPermissionAllDecorator, |
35 HasPermissionAnyApi, HasRepoPermissionAnyApi | 35 HasPermissionAnyDecorator, HasPermissionAnyApi, HasRepoPermissionAnyApi, |
36 HasRepoGroupPermissionAnyApi, HasUserGroupPermissionAny) | |
36 from rhodecode.lib.utils import map_groups, repo2db_mapper | 37 from rhodecode.lib.utils import map_groups, repo2db_mapper |
37 from rhodecode.lib.utils2 import str2bool, time_to_datetime, safe_int | 38 from rhodecode.lib.utils2 import ( |
39 str2bool, time_to_datetime, safe_int, Optional, OAttr) | |
38 from rhodecode.model.meta import Session | 40 from rhodecode.model.meta import Session |
39 from rhodecode.model.scm import ScmModel | 41 from rhodecode.model.repo_group import RepoGroupModel |
42 from rhodecode.model.scm import ScmModel, UserGroupList | |
40 from rhodecode.model.repo import RepoModel | 43 from rhodecode.model.repo import RepoModel |
41 from rhodecode.model.user import UserModel | 44 from rhodecode.model.user import UserModel |
42 from rhodecode.model.users_group import UserGroupModel | 45 from rhodecode.model.user_group import UserGroupModel |
43 from rhodecode.model.repos_group import ReposGroupModel | 46 from rhodecode.model.gist import GistModel |
44 from rhodecode.model.db import Repository, RhodeCodeSetting, UserIpMap,\ | 47 from rhodecode.model.db import ( |
45 Permission, User, Gist | 48 Repository, RhodeCodeSetting, UserIpMap, Permission, User, Gist, |
49 RepoGroup) | |
46 from rhodecode.lib.compat import json | 50 from rhodecode.lib.compat import json |
47 from rhodecode.lib.exceptions import DefaultUserException | 51 from rhodecode.lib.exceptions import ( |
48 from rhodecode.model.gist import GistModel | 52 DefaultUserException, UserGroupsAssignedException) |
49 | 53 |
50 log = logging.getLogger(__name__) | 54 log = logging.getLogger(__name__) |
51 | 55 |
52 | 56 |
53 def store_update(updates, attr, name): | 57 def store_update(updates, attr, name): |
57 """ | 61 """ |
58 if not isinstance(attr, Optional): | 62 if not isinstance(attr, Optional): |
59 updates[name] = attr | 63 updates[name] = attr |
60 | 64 |
61 | 65 |
62 class OptionalAttr(object): | |
63 """ | |
64 Special Optional Option that defines other attribute | |
65 """ | |
66 def __init__(self, attr_name): | |
67 self.attr_name = attr_name | |
68 | |
69 def __repr__(self): | |
70 return '<OptionalAttr:%s>' % self.attr_name | |
71 | |
72 def __call__(self): | |
73 return self | |
74 #alias | |
75 OAttr = OptionalAttr | |
76 | |
77 | |
78 class Optional(object): | |
79 """ | |
80 Defines an optional parameter:: | |
81 | |
82 param = param.getval() if isinstance(param, Optional) else param | |
83 param = param() if isinstance(param, Optional) else param | |
84 | |
85 is equivalent of:: | |
86 | |
87 param = Optional.extract(param) | |
88 | |
89 """ | |
90 def __init__(self, type_): | |
91 self.type_ = type_ | |
92 | |
93 def __repr__(self): | |
94 return '<Optional:%s>' % self.type_.__repr__() | |
95 | |
96 def __call__(self): | |
97 return self.getval() | |
98 | |
99 def getval(self): | |
100 """ | |
101 returns value from this Optional instance | |
102 """ | |
103 return self.type_ | |
104 | |
105 @classmethod | |
106 def extract(cls, val): | |
107 if isinstance(val, cls): | |
108 return val.getval() | |
109 return val | |
110 | |
111 | |
112 def get_user_or_error(userid): | 66 def get_user_or_error(userid): |
113 """ | 67 """ |
114 Get user by id or name or return JsonRPCError if not found | 68 Get user by id or name or return JsonRPCError if not found |
115 | 69 |
116 :param userid: | 70 :param userid: |
117 """ | 71 """ |
118 user = UserModel().get_user(userid) | 72 user = UserModel().get_user(userid) |
119 if user is None: | 73 if user is None: |
120 raise JSONRPCError("user `%s` does not exist" % userid) | 74 raise JSONRPCError("user `%s` does not exist" % (userid,)) |
121 return user | 75 return user |
122 | 76 |
123 | 77 |
124 def get_repo_or_error(repoid): | 78 def get_repo_or_error(repoid): |
125 """ | 79 """ |
127 | 81 |
128 :param repoid: | 82 :param repoid: |
129 """ | 83 """ |
130 repo = RepoModel().get_repo(repoid) | 84 repo = RepoModel().get_repo(repoid) |
131 if repo is None: | 85 if repo is None: |
132 raise JSONRPCError('repository `%s` does not exist' % (repoid)) | 86 raise JSONRPCError('repository `%s` does not exist' % (repoid,)) |
133 return repo | 87 return repo |
134 | 88 |
135 | 89 |
136 def get_repo_group_or_error(repogroupid): | 90 def get_repo_group_or_error(repogroupid): |
137 """ | 91 """ |
138 Get repo group by id or name or return JsonRPCError if not found | 92 Get repo group by id or name or return JsonRPCError if not found |
139 | 93 |
140 :param repogroupid: | 94 :param repogroupid: |
141 """ | 95 """ |
142 repo_group = ReposGroupModel()._get_repo_group(repogroupid) | 96 repo_group = RepoGroupModel()._get_repo_group(repogroupid) |
143 if repo_group is None: | 97 if repo_group is None: |
144 raise JSONRPCError( | 98 raise JSONRPCError( |
145 'repository group `%s` does not exist' % (repogroupid,)) | 99 'repository group `%s` does not exist' % (repogroupid,)) |
146 return repo_group | 100 return repo_group |
147 | 101 |
148 | 102 |
149 def get_users_group_or_error(usersgroupid): | 103 def get_user_group_or_error(usergroupid): |
150 """ | 104 """ |
151 Get user group by id or name or return JsonRPCError if not found | 105 Get user group by id or name or return JsonRPCError if not found |
152 | 106 |
153 :param userid: | 107 :param usergroupid: |
154 """ | 108 """ |
155 users_group = UserGroupModel().get_group(usersgroupid) | 109 user_group = UserGroupModel().get_group(usergroupid) |
156 if users_group is None: | 110 if user_group is None: |
157 raise JSONRPCError('user group `%s` does not exist' % usersgroupid) | 111 raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) |
158 return users_group | 112 return user_group |
159 | 113 |
160 | 114 |
161 def get_perm_or_error(permid): | 115 def get_perm_or_error(permid, prefix=None): |
162 """ | 116 """ |
163 Get permission by id or name or return JsonRPCError if not found | 117 Get permission by id or name or return JsonRPCError if not found |
164 | 118 |
165 :param userid: | 119 :param permid: |
166 """ | 120 """ |
167 perm = Permission.get_by_key(permid) | 121 perm = Permission.get_by_key(permid) |
168 if perm is None: | 122 if perm is None: |
169 raise JSONRPCError('permission `%s` does not exist' % (permid)) | 123 raise JSONRPCError('permission `%s` does not exist' % (permid,)) |
124 if prefix: | |
125 if not perm.permission_name.startswith(prefix): | |
126 raise JSONRPCError('permission `%s` is invalid, ' | |
127 'should start with %s' % (permid, prefix)) | |
170 return perm | 128 return perm |
129 | |
130 | |
131 def get_gist_or_error(gistid): | |
132 """ | |
133 Get gist by id or gist_access_id or return JsonRPCError if not found | |
134 | |
135 :param gistid: | |
136 """ | |
137 gist = GistModel().get_gist(gistid) | |
138 if gist is None: | |
139 raise JSONRPCError('gist `%s` does not exist' % (gistid,)) | |
140 return gist | |
171 | 141 |
172 | 142 |
173 class ApiController(JSONRPCController): | 143 class ApiController(JSONRPCController): |
174 """ | 144 """ |
175 API Controller | 145 API Controller |
176 | 146 |
177 | 147 Each method takes USER as first argument. This is then, based on given |
178 Each method needs to have USER as argument this is then based on given | 148 API_KEY propagated as instance of user object who's making the call. |
179 API_KEY propagated as instance of user object | 149 |
180 | 150 example function:: |
181 Preferably this should be first argument also | 151 |
182 | 152 def func(apiuser,arg1, arg2,...): |
153 pass | |
183 | 154 |
184 Each function should also **raise** JSONRPCError for any | 155 Each function should also **raise** JSONRPCError for any |
185 errors that happens | 156 errors that happens. |
186 | 157 |
187 """ | 158 """ |
159 | |
160 @HasPermissionAllDecorator('hg.admin') | |
161 def test(self, apiuser, args): | |
162 return args | |
188 | 163 |
189 @HasPermissionAllDecorator('hg.admin') | 164 @HasPermissionAllDecorator('hg.admin') |
190 def pull(self, apiuser, repoid): | 165 def pull(self, apiuser, repoid): |
191 """ | 166 """ |
192 Dispatch pull action on given repo | 167 Triggers a pull from remote location on given repo. Can be used to |
193 | 168 automatically keep remote repos up to date. This command can be executed |
194 :param apiuser: | 169 only using api_key belonging to user with admin rights |
195 :param repoid: | 170 |
171 :param apiuser: filled automatically from apikey | |
172 :type apiuser: AuthUser | |
173 :param repoid: repository name or repository id | |
174 :type repoid: str or int | |
175 | |
176 OUTPUT:: | |
177 | |
178 id : <id_given_in_input> | |
179 result : { | |
180 "msg": "Pulled from `<repository name>`" | |
181 "repository": "<repository name>" | |
182 } | |
183 error : null | |
184 | |
185 ERROR OUTPUT:: | |
186 | |
187 id : <id_given_in_input> | |
188 result : null | |
189 error : { | |
190 "Unable to pull changes from `<reponame>`" | |
191 } | |
192 | |
196 """ | 193 """ |
197 | 194 |
198 repo = get_repo_or_error(repoid) | 195 repo = get_repo_or_error(repoid) |
199 | 196 |
200 try: | 197 try: |
201 ScmModel().pull_changes(repo.repo_name, | 198 ScmModel().pull_changes(repo.repo_name, |
202 self.rhodecode_user.username) | 199 self.rhodecode_user.username) |
203 return 'Pulled from `%s`' % repo.repo_name | 200 return dict( |
201 msg='Pulled from `%s`' % repo.repo_name, | |
202 repository=repo.repo_name | |
203 ) | |
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 'Unable to pull changes from `%s`' % repo.repo_name | 207 'Unable to pull changes from `%s`' % repo.repo_name |
208 ) | 208 ) |
209 | 209 |
210 @HasPermissionAllDecorator('hg.admin') | 210 @HasPermissionAllDecorator('hg.admin') |
211 def rescan_repos(self, apiuser, remove_obsolete=Optional(False)): | 211 def rescan_repos(self, apiuser, remove_obsolete=Optional(False)): |
212 """ | 212 """ |
213 Dispatch rescan repositories action. If remove_obsolete is set | 213 Triggers rescan repositories action. If remove_obsolete is set |
214 than also delete repos that are in database but not in the filesystem. | 214 than also delete repos that are in database but not in the filesystem. |
215 aka "clean zombies" | 215 aka "clean zombies". This command can be executed only using api_key |
216 | 216 belonging to user with admin rights. |
217 :param apiuser: | 217 |
218 :param remove_obsolete: | 218 :param apiuser: filled automatically from apikey |
219 :type apiuser: AuthUser | |
220 :param remove_obsolete: deletes repositories from | |
221 database that are not found on the filesystem | |
222 :type remove_obsolete: Optional(bool) | |
223 | |
224 OUTPUT:: | |
225 | |
226 id : <id_given_in_input> | |
227 result : { | |
228 'added': [<added repository name>,...] | |
229 'removed': [<removed repository name>,...] | |
230 } | |
231 error : null | |
232 | |
233 ERROR OUTPUT:: | |
234 | |
235 id : <id_given_in_input> | |
236 result : null | |
237 error : { | |
238 'Error occurred during rescan repositories action' | |
239 } | |
240 | |
219 """ | 241 """ |
220 | 242 |
221 try: | 243 try: |
222 rm_obsolete = Optional.extract(remove_obsolete) | 244 rm_obsolete = Optional.extract(remove_obsolete) |
223 added, removed = repo2db_mapper(ScmModel().repo_scan(), | 245 added, removed = repo2db_mapper(ScmModel().repo_scan(), |
229 'Error occurred during rescan repositories action' | 251 'Error occurred during rescan repositories action' |
230 ) | 252 ) |
231 | 253 |
232 def invalidate_cache(self, apiuser, repoid): | 254 def invalidate_cache(self, apiuser, repoid): |
233 """ | 255 """ |
234 Dispatch cache invalidation action on given repo | 256 Invalidate cache for repository. |
235 | 257 This command can be executed only using api_key belonging to user with admin |
236 :param apiuser: | 258 rights or regular user that have write or admin or write access to repository. |
237 :param repoid: | 259 |
260 :param apiuser: filled automatically from apikey | |
261 :type apiuser: AuthUser | |
262 :param repoid: repository name or repository id | |
263 :type repoid: str or int | |
264 | |
265 OUTPUT:: | |
266 | |
267 id : <id_given_in_input> | |
268 result : { | |
269 'msg': Cache for repository `<repository name>` was invalidated, | |
270 'repository': <repository name> | |
271 } | |
272 error : null | |
273 | |
274 ERROR OUTPUT:: | |
275 | |
276 id : <id_given_in_input> | |
277 result : null | |
278 error : { | |
279 'Error occurred during cache invalidation action' | |
280 } | |
281 | |
238 """ | 282 """ |
239 repo = get_repo_or_error(repoid) | 283 repo = get_repo_or_error(repoid) |
240 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | 284 if not HasPermissionAnyApi('hg.admin')(user=apiuser): |
241 # check if we have admin permission for this repo ! | 285 # check if we have admin permission for this repo ! |
242 if HasRepoPermissionAnyApi('repository.admin', | 286 if not HasRepoPermissionAnyApi('repository.admin', |
243 'repository.write')(user=apiuser, | 287 'repository.write')( |
244 repo_name=repo.repo_name) is False: | 288 user=apiuser, repo_name=repo.repo_name): |
245 raise JSONRPCError('repository `%s` does not exist' % (repoid)) | 289 raise JSONRPCError('repository `%s` does not exist' % (repoid,)) |
246 | 290 |
247 try: | 291 try: |
248 ScmModel().mark_for_invalidation(repo.repo_name) | 292 ScmModel().mark_for_invalidation(repo.repo_name) |
249 return ('Caches of repository `%s` was invalidated' % repoid) | 293 return dict( |
294 msg='Cache for repository `%s` was invalidated' % (repoid,), | |
295 repository=repo.repo_name | |
296 ) | |
250 except Exception: | 297 except Exception: |
251 log.error(traceback.format_exc()) | 298 log.error(traceback.format_exc()) |
252 raise JSONRPCError( | 299 raise JSONRPCError( |
253 'Error occurred during cache invalidation action' | 300 'Error occurred during cache invalidation action' |
254 ) | 301 ) |
255 | 302 |
256 # permission check inside | 303 # permission check inside |
257 def lock(self, apiuser, repoid, locked=Optional(None), | 304 def lock(self, apiuser, repoid, locked=Optional(None), |
258 userid=Optional(OAttr('apiuser'))): | 305 userid=Optional(OAttr('apiuser'))): |
259 """ | 306 """ |
260 Set locking state on particular repository by given user, if | 307 Set locking state on given repository by given user. If userid param |
261 this command is runned by non-admin account userid is set to user | 308 is skipped, then it is set to id of user whos calling this method. |
262 who is calling this method | 309 If locked param is skipped then function shows current lock state of |
263 | 310 given repo. This command can be executed only using api_key belonging |
264 :param apiuser: | 311 to user with admin rights or regular user that have admin or write |
265 :param repoid: | 312 access to repository. |
266 :param userid: | 313 |
267 :param locked: | 314 :param apiuser: filled automatically from apikey |
315 :type apiuser: AuthUser | |
316 :param repoid: repository name or repository id | |
317 :type repoid: str or int | |
318 :param locked: lock state to be set | |
319 :type locked: Optional(bool) | |
320 :param userid: set lock as user | |
321 :type userid: Optional(str or int) | |
322 | |
323 OUTPUT:: | |
324 | |
325 id : <id_given_in_input> | |
326 result : { | |
327 'repo': '<reponame>', | |
328 'locked': <bool: lock state>, | |
329 'locked_since': <int: lock timestamp>, | |
330 'locked_by': <username of person who made the lock>, | |
331 'lock_state_changed': <bool: True if lock state has been changed in this request>, | |
332 'msg': 'Repo `<reponame>` locked by `<username>` on <timestamp>.' | |
333 or | |
334 'msg': 'Repo `<repository name>` not locked.' | |
335 or | |
336 'msg': 'User `<user name>` set lock state for repo `<repository name>` to `<new lock state>`' | |
337 } | |
338 error : null | |
339 | |
340 ERROR OUTPUT:: | |
341 | |
342 id : <id_given_in_input> | |
343 result : null | |
344 error : { | |
345 'Error occurred locking repository `<reponame>` | |
346 } | |
347 | |
268 """ | 348 """ |
269 repo = get_repo_or_error(repoid) | 349 repo = get_repo_or_error(repoid) |
270 if HasPermissionAnyApi('hg.admin')(user=apiuser): | 350 if HasPermissionAnyApi('hg.admin')(user=apiuser): |
271 pass | 351 pass |
272 elif HasRepoPermissionAnyApi('repository.admin', | 352 elif HasRepoPermissionAnyApi('repository.admin', |
273 'repository.write')(user=apiuser, | 353 'repository.write')(user=apiuser, |
274 repo_name=repo.repo_name): | 354 repo_name=repo.repo_name): |
275 #make sure normal user does not pass someone else userid, | 355 # make sure normal user does not pass someone else userid, |
276 #he is not allowed to do that | 356 # he is not allowed to do that |
277 if not isinstance(userid, Optional) and userid != apiuser.user_id: | 357 if not isinstance(userid, Optional) and userid != apiuser.user_id: |
278 raise JSONRPCError( | 358 raise JSONRPCError( |
279 'userid is not the same as your user' | 359 'userid is not the same as your user' |
280 ) | 360 ) |
281 else: | 361 else: |
282 raise JSONRPCError('repository `%s` does not exist' % (repoid)) | 362 raise JSONRPCError('repository `%s` does not exist' % (repoid,)) |
283 | 363 |
284 if isinstance(userid, Optional): | 364 if isinstance(userid, Optional): |
285 userid = apiuser.user_id | 365 userid = apiuser.user_id |
286 | 366 |
287 user = get_user_or_error(userid) | 367 user = get_user_or_error(userid) |
293 _d = { | 373 _d = { |
294 'repo': repo.repo_name, | 374 'repo': repo.repo_name, |
295 'locked': False, | 375 'locked': False, |
296 'locked_since': None, | 376 'locked_since': None, |
297 'locked_by': None, | 377 'locked_by': None, |
378 'lock_state_changed': False, | |
298 'msg': 'Repo `%s` not locked.' % repo.repo_name | 379 'msg': 'Repo `%s` not locked.' % repo.repo_name |
299 } | 380 } |
300 return _d | 381 return _d |
301 else: | 382 else: |
302 userid, time_ = lockobj | 383 userid, time_ = lockobj |
304 _d = { | 385 _d = { |
305 'repo': repo.repo_name, | 386 'repo': repo.repo_name, |
306 'locked': True, | 387 'locked': True, |
307 'locked_since': time_, | 388 'locked_since': time_, |
308 'locked_by': lock_user.username, | 389 'locked_by': lock_user.username, |
309 'msg': ('Repo `%s` locked by `%s`. ' | 390 'lock_state_changed': False, |
310 % (repo.repo_name, | 391 'msg': ('Repo `%s` locked by `%s` on `%s`.' |
392 % (repo.repo_name, lock_user.username, | |
311 json.dumps(time_to_datetime(time_)))) | 393 json.dumps(time_to_datetime(time_)))) |
312 } | 394 } |
313 return _d | 395 return _d |
314 | 396 |
315 # force locked state through a flag | 397 # force locked state through a flag |
325 _d = { | 407 _d = { |
326 'repo': repo.repo_name, | 408 'repo': repo.repo_name, |
327 'locked': locked, | 409 'locked': locked, |
328 'locked_since': lock_time, | 410 'locked_since': lock_time, |
329 'locked_by': user.username, | 411 'locked_by': user.username, |
412 'lock_state_changed': True, | |
330 'msg': ('User `%s` set lock state for repo `%s` to `%s`' | 413 'msg': ('User `%s` set lock state for repo `%s` to `%s`' |
331 % (user.username, repo.repo_name, locked)) | 414 % (user.username, repo.repo_name, locked)) |
332 } | 415 } |
333 return _d | 416 return _d |
334 except Exception: | 417 except Exception: |
337 'Error occurred locking repository `%s`' % repo.repo_name | 420 'Error occurred locking repository `%s`' % repo.repo_name |
338 ) | 421 ) |
339 | 422 |
340 def get_locks(self, apiuser, userid=Optional(OAttr('apiuser'))): | 423 def get_locks(self, apiuser, userid=Optional(OAttr('apiuser'))): |
341 """ | 424 """ |
342 Get all locks for given userid, if | 425 Get all repositories with locks for given userid, if |
343 this command is runned by non-admin account userid is set to user | 426 this command is runned by non-admin account userid is set to user |
344 who is calling this method, thus returning locks for himself | 427 who is calling this method, thus returning locks for himself. |
345 | 428 |
346 :param apiuser: | 429 :param apiuser: filled automatically from apikey |
347 :param userid: | 430 :type apiuser: AuthUser |
431 :param userid: User to get locks for | |
432 :type userid: Optional(str or int) | |
433 | |
434 OUTPUT:: | |
435 | |
436 id : <id_given_in_input> | |
437 result : { | |
438 [repo_object, repo_object,...] | |
439 } | |
440 error : null | |
348 """ | 441 """ |
349 | 442 |
350 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | 443 if not HasPermissionAnyApi('hg.admin')(user=apiuser): |
351 #make sure normal user does not pass someone else userid, | 444 # make sure normal user does not pass someone else userid, |
352 #he is not allowed to do that | 445 # he is not allowed to do that |
353 if not isinstance(userid, Optional) and userid != apiuser.user_id: | 446 if not isinstance(userid, Optional) and userid != apiuser.user_id: |
354 raise JSONRPCError( | 447 raise JSONRPCError( |
355 'userid is not the same as your user' | 448 'userid is not the same as your user' |
356 ) | 449 ) |
450 | |
357 ret = [] | 451 ret = [] |
358 if isinstance(userid, Optional): | 452 if isinstance(userid, Optional): |
359 user = None | 453 user = None |
360 else: | 454 else: |
361 user = get_user_or_error(userid) | 455 user = get_user_or_error(userid) |
362 | 456 |
363 #show all locks | 457 # show all locks |
364 for r in Repository.getAll(): | 458 for r in Repository.getAll(): |
365 userid, time_ = r.locked | 459 userid, time_ = r.locked |
366 if time_: | 460 if time_: |
367 _api_data = r.get_api_data() | 461 _api_data = r.get_api_data() |
368 # if we use userfilter just show the locks for this user | 462 # if we use userfilter just show the locks for this user |
373 ret.append(_api_data) | 467 ret.append(_api_data) |
374 | 468 |
375 return ret | 469 return ret |
376 | 470 |
377 @HasPermissionAllDecorator('hg.admin') | 471 @HasPermissionAllDecorator('hg.admin') |
378 def show_ip(self, apiuser, userid): | 472 def get_ip(self, apiuser, userid=Optional(OAttr('apiuser'))): |
379 """ | 473 """ |
380 Shows IP address as seen from RhodeCode server, together with all | 474 Shows IP address as seen from RhodeCode server, together with all |
381 defined IP addresses for given user | 475 defined IP addresses for given user. If userid is not passed data is |
382 | 476 returned for user who's calling this function. |
383 :param apiuser: | 477 This command can be executed only using api_key belonging to user with |
384 :param userid: | 478 admin rights. |
385 """ | 479 |
480 :param apiuser: filled automatically from apikey | |
481 :type apiuser: AuthUser | |
482 :param userid: username to show ips for | |
483 :type userid: Optional(str or int) | |
484 | |
485 OUTPUT:: | |
486 | |
487 id : <id_given_in_input> | |
488 result : { | |
489 "server_ip_addr": "<ip_from_clien>", | |
490 "user_ips": [ | |
491 { | |
492 "ip_addr": "<ip_with_mask>", | |
493 "ip_range": ["<start_ip>", "<end_ip>"], | |
494 }, | |
495 ... | |
496 ] | |
497 } | |
498 | |
499 """ | |
500 if isinstance(userid, Optional): | |
501 userid = apiuser.user_id | |
386 user = get_user_or_error(userid) | 502 user = get_user_or_error(userid) |
387 ips = UserIpMap.query().filter(UserIpMap.user == user).all() | 503 ips = UserIpMap.query().filter(UserIpMap.user == user).all() |
388 return dict( | 504 return dict( |
389 ip_addr_server=self.ip_addr, | 505 server_ip_addr=self.ip_addr, |
390 user_ips=ips | 506 user_ips=ips |
391 ) | 507 ) |
392 | 508 |
509 # alias for old | |
510 show_ip = get_ip | |
511 | |
512 @HasPermissionAllDecorator('hg.admin') | |
513 def get_server_info(self, apiuser): | |
514 """ | |
515 return server info, including RhodeCode version and installed packages | |
516 | |
517 :param apiuser: filled automatically from apikey | |
518 :type apiuser: AuthUser | |
519 | |
520 OUTPUT:: | |
521 | |
522 id : <id_given_in_input> | |
523 result : { | |
524 'modules': [<module name>,...] | |
525 'py_version': <python version>, | |
526 'platform': <platform type>, | |
527 'rhodecode_version': <rhodecode version> | |
528 } | |
529 error : null | |
530 """ | |
531 return RhodeCodeSetting.get_server_info() | |
532 | |
393 def get_user(self, apiuser, userid=Optional(OAttr('apiuser'))): | 533 def get_user(self, apiuser, userid=Optional(OAttr('apiuser'))): |
394 """" | 534 """ |
395 Get a user by username, or userid, if userid is given | 535 Get's an user by username or user_id, Returns empty result if user is |
396 | 536 not found. If userid param is skipped it is set to id of user who is |
397 :param apiuser: | 537 calling this method. This command can be executed only using api_key |
398 :param userid: | 538 belonging to user with admin rights, or regular users that cannot |
539 specify different userid than theirs | |
540 | |
541 :param apiuser: filled automatically from apikey | |
542 :type apiuser: AuthUser | |
543 :param userid: user to get data for | |
544 :type userid: Optional(str or int) | |
545 | |
546 OUTPUT:: | |
547 | |
548 id : <id_given_in_input> | |
549 result: None if user does not exist or | |
550 { | |
551 "user_id" : "<user_id>", | |
552 "api_key" : "<api_key>", | |
553 "api_keys": "[<list of all api keys including additional ones>]" | |
554 "username" : "<username>", | |
555 "firstname": "<firstname>", | |
556 "lastname" : "<lastname>", | |
557 "email" : "<email>", | |
558 "emails": "[<list of all emails including additional ones>]", | |
559 "ip_addresses": "[<ip_addresse_for_user>,...]", | |
560 "active" : "<bool: user active>", | |
561 "admin" :ย "<bool: user is admin>", | |
562 "extern_name" : "<extern_name>", | |
563 "extern_type" : "<extern type> | |
564 "last_login": "<last_login>", | |
565 "permissions": { | |
566 "global": ["hg.create.repository", | |
567 "repository.read", | |
568 "hg.register.manual_activate"], | |
569 "repositories": {"repo1": "repository.none"}, | |
570 "repositories_groups": {"Group1": "group.read"} | |
571 }, | |
572 } | |
573 | |
574 error: null | |
575 | |
399 """ | 576 """ |
400 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | 577 if not HasPermissionAnyApi('hg.admin')(user=apiuser): |
401 #make sure normal user does not pass someone else userid, | 578 # make sure normal user does not pass someone else userid, |
402 #he is not allowed to do that | 579 # he is not allowed to do that |
403 if not isinstance(userid, Optional) and userid != apiuser.user_id: | 580 if not isinstance(userid, Optional) and userid != apiuser.user_id: |
404 raise JSONRPCError( | 581 raise JSONRPCError( |
405 'userid is not the same as your user' | 582 'userid is not the same as your user' |
406 ) | 583 ) |
407 | 584 |
413 data['permissions'] = AuthUser(user_id=user.user_id).permissions | 590 data['permissions'] = AuthUser(user_id=user.user_id).permissions |
414 return data | 591 return data |
415 | 592 |
416 @HasPermissionAllDecorator('hg.admin') | 593 @HasPermissionAllDecorator('hg.admin') |
417 def get_users(self, apiuser): | 594 def get_users(self, apiuser): |
418 """" | 595 """ |
419 Get all users | 596 Lists all existing users. This command can be executed only using api_key |
420 | 597 belonging to user with admin rights. |
421 :param apiuser: | 598 |
599 :param apiuser: filled automatically from apikey | |
600 :type apiuser: AuthUser | |
601 | |
602 OUTPUT:: | |
603 | |
604 id : <id_given_in_input> | |
605 result: [<user_object>, ...] | |
606 error: null | |
422 """ | 607 """ |
423 | 608 |
424 result = [] | 609 result = [] |
425 users_list = User.query().order_by(User.username)\ | 610 users_list = User.query().order_by(User.username) \ |
426 .filter(User.username != User.DEFAULT_USER)\ | 611 .filter(User.username != User.DEFAULT_USER) \ |
427 .all() | 612 .all() |
428 for user in users_list: | 613 for user in users_list: |
429 result.append(user.get_api_data()) | 614 result.append(user.get_api_data()) |
430 return result | 615 return result |
431 | 616 |
432 @HasPermissionAllDecorator('hg.admin') | 617 @HasPermissionAllDecorator('hg.admin') |
433 def create_user(self, apiuser, username, email, password=Optional(None), | 618 def create_user(self, apiuser, username, email, password=Optional(''), |
434 firstname=Optional(None), lastname=Optional(None), | 619 firstname=Optional(''), lastname=Optional(''), |
435 active=Optional(True), admin=Optional(False), | 620 active=Optional(True), admin=Optional(False), |
436 ldap_dn=Optional(None)): | 621 extern_name=Optional('rhodecode'), |
437 """ | 622 extern_type=Optional('rhodecode')): |
438 Create new user | 623 """ |
439 | 624 Creates new user. Returns new user object. This command can |
440 :param apiuser: | 625 be executed only using api_key belonging to user with admin rights. |
441 :param username: | 626 |
442 :param email: | 627 :param apiuser: filled automatically from apikey |
443 :param password: | 628 :type apiuser: AuthUser |
444 :param firstname: | 629 :param username: new username |
445 :param lastname: | 630 :type username: str or int |
446 :param active: | 631 :param email: email |
447 :param admin: | 632 :type email: str |
448 :param ldap_dn: | 633 :param password: password |
634 :type password: Optional(str) | |
635 :param firstname: firstname | |
636 :type firstname: Optional(str) | |
637 :param lastname: lastname | |
638 :type lastname: Optional(str) | |
639 :param active: active | |
640 :type active: Optional(bool) | |
641 :param admin: admin | |
642 :type admin: Optional(bool) | |
643 :param extern_name: name of extern | |
644 :type extern_name: Optional(str) | |
645 :param extern_type: extern_type | |
646 :type extern_type: Optional(str) | |
647 | |
648 | |
649 OUTPUT:: | |
650 | |
651 id : <id_given_in_input> | |
652 result: { | |
653 "msg" : "created new user `<username>`", | |
654 "user": <user_obj> | |
655 } | |
656 error: null | |
657 | |
658 ERROR OUTPUT:: | |
659 | |
660 id : <id_given_in_input> | |
661 result : null | |
662 error : { | |
663 "user `<username>` already exist" | |
664 or | |
665 "email `<email>` already exist" | |
666 or | |
667 "failed to create user `<username>`" | |
668 } | |
669 | |
449 """ | 670 """ |
450 | 671 |
451 if UserModel().get_by_username(username): | 672 if UserModel().get_by_username(username): |
452 raise JSONRPCError("user `%s` already exist" % username) | 673 raise JSONRPCError("user `%s` already exist" % (username,)) |
453 | 674 |
454 if UserModel().get_by_email(email, case_insensitive=True): | 675 if UserModel().get_by_email(email, case_insensitive=True): |
455 raise JSONRPCError("email `%s` already exist" % email) | 676 raise JSONRPCError("email `%s` already exist" % (email,)) |
456 | 677 |
457 if Optional.extract(ldap_dn): | 678 if Optional.extract(extern_name): |
458 # generate temporary password if ldap_dn | 679 # generate temporary password if user is external |
459 password = PasswordGenerator().gen_password(length=8) | 680 password = PasswordGenerator().gen_password(length=8) |
460 | 681 |
461 try: | 682 try: |
462 user = UserModel().create_or_update( | 683 user = UserModel().create_or_update( |
463 username=Optional.extract(username), | 684 username=Optional.extract(username), |
465 email=Optional.extract(email), | 686 email=Optional.extract(email), |
466 firstname=Optional.extract(firstname), | 687 firstname=Optional.extract(firstname), |
467 lastname=Optional.extract(lastname), | 688 lastname=Optional.extract(lastname), |
468 active=Optional.extract(active), | 689 active=Optional.extract(active), |
469 admin=Optional.extract(admin), | 690 admin=Optional.extract(admin), |
470 ldap_dn=Optional.extract(ldap_dn) | 691 extern_type=Optional.extract(extern_type), |
692 extern_name=Optional.extract(extern_name) | |
471 ) | 693 ) |
472 Session().commit() | 694 Session().commit() |
473 return dict( | 695 return dict( |
474 msg='created new user `%s`' % username, | 696 msg='created new user `%s`' % username, |
475 user=user.get_api_data() | 697 user=user.get_api_data() |
476 ) | 698 ) |
477 except Exception: | 699 except Exception: |
478 log.error(traceback.format_exc()) | 700 log.error(traceback.format_exc()) |
479 raise JSONRPCError('failed to create user `%s`' % username) | 701 raise JSONRPCError('failed to create user `%s`' % (username,)) |
480 | 702 |
481 @HasPermissionAllDecorator('hg.admin') | 703 @HasPermissionAllDecorator('hg.admin') |
482 def update_user(self, apiuser, userid, username=Optional(None), | 704 def update_user(self, apiuser, userid, username=Optional(None), |
483 email=Optional(None), firstname=Optional(None), | 705 email=Optional(None),password=Optional(None), |
484 lastname=Optional(None), active=Optional(None), | 706 firstname=Optional(None), lastname=Optional(None), |
485 admin=Optional(None), ldap_dn=Optional(None), | 707 active=Optional(None), admin=Optional(None), |
486 password=Optional(None)): | 708 extern_type=Optional(None), extern_name=Optional(None),): |
487 """ | 709 """ |
488 Updates given user | 710 updates given user if such user exists. This command can |
489 | 711 be executed only using api_key belonging to user with admin rights. |
490 :param apiuser: | 712 |
491 :param userid: | 713 :param apiuser: filled automatically from apikey |
492 :param username: | 714 :type apiuser: AuthUser |
493 :param email: | 715 :param userid: userid to update |
494 :param firstname: | 716 :type userid: str or int |
495 :param lastname: | 717 :param username: new username |
496 :param active: | 718 :type username: str or int |
497 :param admin: | 719 :param email: email |
498 :param ldap_dn: | 720 :type email: str |
499 :param password: | 721 :param password: password |
722 :type password: Optional(str) | |
723 :param firstname: firstname | |
724 :type firstname: Optional(str) | |
725 :param lastname: lastname | |
726 :type lastname: Optional(str) | |
727 :param active: active | |
728 :type active: Optional(bool) | |
729 :param admin: admin | |
730 :type admin: Optional(bool) | |
731 :param extern_name: | |
732 :type extern_name: Optional(str) | |
733 :param extern_type: | |
734 :type extern_type: Optional(str) | |
735 | |
736 | |
737 OUTPUT:: | |
738 | |
739 id : <id_given_in_input> | |
740 result: { | |
741 "msg" : "updated user ID:<userid> <username>", | |
742 "user": <user_object>, | |
743 } | |
744 error: null | |
745 | |
746 ERROR OUTPUT:: | |
747 | |
748 id : <id_given_in_input> | |
749 result : null | |
750 error : { | |
751 "failed to update user `<username>`" | |
752 } | |
753 | |
500 """ | 754 """ |
501 | 755 |
502 user = get_user_or_error(userid) | 756 user = get_user_or_error(userid) |
503 | 757 |
504 # call function and store only updated arguments | 758 # only non optional arguments will be stored in updates |
505 updates = {} | 759 updates = {} |
506 | 760 |
507 def store_update(attr, name): | 761 try: |
508 if not isinstance(attr, Optional): | 762 |
509 updates[name] = attr | 763 store_update(updates, username, 'username') |
510 | 764 store_update(updates, password, 'password') |
511 try: | 765 store_update(updates, email, 'email') |
512 | 766 store_update(updates, firstname, 'name') |
513 store_update(username, 'username') | 767 store_update(updates, lastname, 'lastname') |
514 store_update(password, 'password') | 768 store_update(updates, active, 'active') |
515 store_update(email, 'email') | 769 store_update(updates, admin, 'admin') |
516 store_update(firstname, 'name') | 770 store_update(updates, extern_name, 'extern_name') |
517 store_update(lastname, 'lastname') | 771 store_update(updates, extern_type, 'extern_type') |
518 store_update(active, 'active') | |
519 store_update(admin, 'admin') | |
520 store_update(ldap_dn, 'ldap_dn') | |
521 | 772 |
522 user = UserModel().update_user(user, **updates) | 773 user = UserModel().update_user(user, **updates) |
523 Session().commit() | 774 Session().commit() |
524 return dict( | 775 return dict( |
525 msg='updated user ID:%s %s' % (user.user_id, user.username), | 776 msg='updated user ID:%s %s' % (user.user_id, user.username), |
528 except DefaultUserException: | 779 except DefaultUserException: |
529 log.error(traceback.format_exc()) | 780 log.error(traceback.format_exc()) |
530 raise JSONRPCError('editing default user is forbidden') | 781 raise JSONRPCError('editing default user is forbidden') |
531 except Exception: | 782 except Exception: |
532 log.error(traceback.format_exc()) | 783 log.error(traceback.format_exc()) |
533 raise JSONRPCError('failed to update user `%s`' % userid) | 784 raise JSONRPCError('failed to update user `%s`' % (userid,)) |
534 | 785 |
535 @HasPermissionAllDecorator('hg.admin') | 786 @HasPermissionAllDecorator('hg.admin') |
536 def delete_user(self, apiuser, userid): | 787 def delete_user(self, apiuser, userid): |
537 """" | 788 """ |
538 Deletes an user | 789 deletes givenuser if such user exists. This command can |
539 | 790 be executed only using api_key belonging to user with admin rights. |
540 :param apiuser: | 791 |
541 :param userid: | 792 :param apiuser: filled automatically from apikey |
793 :type apiuser: AuthUser | |
794 :param userid: user to delete | |
795 :type userid: str or int | |
796 | |
797 OUTPUT:: | |
798 | |
799 id : <id_given_in_input> | |
800 result: { | |
801 "msg" : "deleted user ID:<userid> <username>", | |
802 "user": null | |
803 } | |
804 error: null | |
805 | |
806 ERROR OUTPUT:: | |
807 | |
808 id : <id_given_in_input> | |
809 result : null | |
810 error : { | |
811 "failed to delete user ID:<userid> <username>" | |
812 } | |
813 | |
542 """ | 814 """ |
543 user = get_user_or_error(userid) | 815 user = get_user_or_error(userid) |
544 | 816 |
545 try: | 817 try: |
546 UserModel().delete(userid) | 818 UserModel().delete(userid) |
548 return dict( | 820 return dict( |
549 msg='deleted user ID:%s %s' % (user.user_id, user.username), | 821 msg='deleted user ID:%s %s' % (user.user_id, user.username), |
550 user=None | 822 user=None |
551 ) | 823 ) |
552 except Exception: | 824 except Exception: |
553 log.error(traceback.format_exc()) | 825 |
554 raise JSONRPCError('failed to delete ID:%s %s' % (user.user_id, | 826 log.error(traceback.format_exc()) |
555 user.username)) | 827 raise JSONRPCError('failed to delete user ID:%s %s' |
556 | 828 % (user.user_id, user.username)) |
557 @HasPermissionAllDecorator('hg.admin') | 829 |
558 def get_users_group(self, apiuser, usersgroupid): | 830 # permission check inside |
559 """" | 831 def get_user_group(self, apiuser, usergroupid): |
560 Get user group by name or id | 832 """ |
561 | 833 Gets an existing user group. This command can be executed only using api_key |
562 :param apiuser: | 834 belonging to user with admin rights or user who has at least |
563 :param usersgroupid: | 835 read access to user group. |
564 """ | 836 |
565 users_group = get_users_group_or_error(usersgroupid) | 837 :param apiuser: filled automatically from apikey |
566 | 838 :type apiuser: AuthUser |
567 data = users_group.get_api_data() | 839 :param usergroupid: id of user_group to edit |
568 | 840 :type usergroupid: str or int |
569 members = [] | 841 |
570 for user in users_group.members: | 842 OUTPUT:: |
571 user = user.user | 843 |
572 members.append(user.get_api_data()) | 844 id : <id_given_in_input> |
573 data['members'] = members | 845 result : None if group not exist |
846 { | |
847 "users_group_id" : "<id>", | |
848 "group_name" : "<groupname>", | |
849 "active": "<bool>", | |
850 "members" : [<user_obj>,...] | |
851 } | |
852 error : null | |
853 | |
854 """ | |
855 user_group = get_user_group_or_error(usergroupid) | |
856 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | |
857 # check if we have at least read permission for this user group ! | |
858 _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',) | |
859 if not HasUserGroupPermissionAny(*_perms)( | |
860 user=apiuser, user_group_name=user_group.users_group_name): | |
861 raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) | |
862 | |
863 data = user_group.get_api_data() | |
574 return data | 864 return data |
575 | 865 |
576 @HasPermissionAllDecorator('hg.admin') | 866 # permission check inside |
577 def get_users_groups(self, apiuser): | 867 def get_user_groups(self, apiuser): |
578 """" | 868 """ |
579 Get all user groups | 869 Lists all existing user groups. This command can be executed only using |
580 | 870 api_key belonging to user with admin rights or user who has at least |
581 :param apiuser: | 871 read access to user group. |
872 | |
873 :param apiuser: filled automatically from apikey | |
874 :type apiuser: AuthUser | |
875 | |
876 OUTPUT:: | |
877 | |
878 id : <id_given_in_input> | |
879 result : [<user_group_obj>,...] | |
880 error : null | |
582 """ | 881 """ |
583 | 882 |
584 result = [] | 883 result = [] |
585 for users_group in UserGroupModel().get_all(): | 884 _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',) |
586 result.append(users_group.get_api_data()) | 885 extras = {'user': apiuser} |
886 for user_group in UserGroupList(UserGroupModel().get_all(), | |
887 perm_set=_perms, extra_kwargs=extras): | |
888 result.append(user_group.get_api_data()) | |
587 return result | 889 return result |
588 | 890 |
589 @HasPermissionAllDecorator('hg.admin') | 891 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true') |
590 def create_users_group(self, apiuser, group_name, | 892 def create_user_group(self, apiuser, group_name, description=Optional(''), |
591 owner=Optional(OAttr('apiuser')), | 893 owner=Optional(OAttr('apiuser')), active=Optional(True)): |
592 active=Optional(True)): | 894 """ |
593 """ | 895 Creates new user group. This command can be executed only using api_key |
594 Creates an new usergroup | 896 belonging to user with admin rights or an user who has create user group |
595 | 897 permission |
596 :param apiuser: | 898 |
597 :param group_name: | 899 :param apiuser: filled automatically from apikey |
598 :param owner: | 900 :type apiuser: AuthUser |
599 :param active: | 901 :param group_name: name of new user group |
902 :type group_name: str | |
903 :param description: group description | |
904 :type description: str | |
905 :param owner: owner of group. If not passed apiuser is the owner | |
906 :type owner: Optional(str or int) | |
907 :param active: group is active | |
908 :type active: Optional(bool) | |
909 | |
910 OUTPUT:: | |
911 | |
912 id : <id_given_in_input> | |
913 result: { | |
914 "msg": "created new user group `<groupname>`", | |
915 "user_group": <user_group_object> | |
916 } | |
917 error: null | |
918 | |
919 ERROR OUTPUT:: | |
920 | |
921 id : <id_given_in_input> | |
922 result : null | |
923 error : { | |
924 "user group `<group name>` already exist" | |
925 or | |
926 "failed to create group `<group name>`" | |
927 } | |
928 | |
600 """ | 929 """ |
601 | 930 |
602 if UserGroupModel().get_by_name(group_name): | 931 if UserGroupModel().get_by_name(group_name): |
603 raise JSONRPCError("user group `%s` already exist" % group_name) | 932 raise JSONRPCError("user group `%s` already exist" % (group_name,)) |
604 | 933 |
605 try: | 934 try: |
606 if isinstance(owner, Optional): | 935 if isinstance(owner, Optional): |
607 owner = apiuser.user_id | 936 owner = apiuser.user_id |
608 | 937 |
609 owner = get_user_or_error(owner) | 938 owner = get_user_or_error(owner) |
610 active = Optional.extract(active) | 939 active = Optional.extract(active) |
611 ug = UserGroupModel().create(name=group_name, | 940 description = Optional.extract(description) |
612 owner=owner, | 941 ug = UserGroupModel().create(name=group_name, description=description, |
613 active=active) | 942 owner=owner, active=active) |
614 Session().commit() | 943 Session().commit() |
615 return dict( | 944 return dict( |
616 msg='created new user group `%s`' % group_name, | 945 msg='created new user group `%s`' % group_name, |
617 users_group=ug.get_api_data() | 946 user_group=ug.get_api_data() |
618 ) | 947 ) |
619 except Exception: | 948 except Exception: |
620 log.error(traceback.format_exc()) | 949 log.error(traceback.format_exc()) |
621 raise JSONRPCError('failed to create group `%s`' % group_name) | 950 raise JSONRPCError('failed to create group `%s`' % (group_name,)) |
622 | 951 |
623 @HasPermissionAllDecorator('hg.admin') | 952 # permission check inside |
624 def add_user_to_users_group(self, apiuser, usersgroupid, userid): | 953 def update_user_group(self, apiuser, usergroupid, group_name=Optional(''), |
625 """" | 954 description=Optional(''), owner=Optional(None), |
626 Add a user to a user group | 955 active=Optional(True)): |
627 | 956 """ |
628 :param apiuser: | 957 Updates given usergroup. This command can be executed only using api_key |
629 :param usersgroupid: | 958 belonging to user with admin rights or an admin of given user group |
959 | |
960 :param apiuser: filled automatically from apikey | |
961 :type apiuser: AuthUser | |
962 :param usergroupid: id of user group to update | |
963 :type usergroupid: str or int | |
964 :param group_name: name of new user group | |
965 :type group_name: str | |
966 :param description: group description | |
967 :type description: str | |
968 :param owner: owner of group. | |
969 :type owner: Optional(str or int) | |
970 :param active: group is active | |
971 :type active: Optional(bool) | |
972 | |
973 OUTPUT:: | |
974 | |
975 id : <id_given_in_input> | |
976 result : { | |
977 "msg": 'updated user group ID:<user group id> <user group name>', | |
978 "user_group": <user_group_object> | |
979 } | |
980 error : null | |
981 | |
982 ERROR OUTPUT:: | |
983 | |
984 id : <id_given_in_input> | |
985 result : null | |
986 error : { | |
987 "failed to update user group `<user group name>`" | |
988 } | |
989 | |
990 """ | |
991 user_group = get_user_group_or_error(usergroupid) | |
992 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | |
993 # check if we have admin permission for this user group ! | |
994 _perms = ('usergroup.admin',) | |
995 if not HasUserGroupPermissionAny(*_perms)( | |
996 user=apiuser, user_group_name=user_group.users_group_name): | |
997 raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) | |
998 | |
999 if not isinstance(owner, Optional): | |
1000 owner = get_user_or_error(owner) | |
1001 | |
1002 updates = {} | |
1003 store_update(updates, group_name, 'users_group_name') | |
1004 store_update(updates, description, 'user_group_description') | |
1005 store_update(updates, owner, 'user') | |
1006 store_update(updates, active, 'users_group_active') | |
1007 try: | |
1008 UserGroupModel().update(user_group, updates) | |
1009 Session().commit() | |
1010 return dict( | |
1011 msg='updated user group ID:%s %s' % (user_group.users_group_id, | |
1012 user_group.users_group_name), | |
1013 user_group=user_group.get_api_data() | |
1014 ) | |
1015 except Exception: | |
1016 log.error(traceback.format_exc()) | |
1017 raise JSONRPCError('failed to update user group `%s`' % (usergroupid,)) | |
1018 | |
1019 # permission check inside | |
1020 def delete_user_group(self, apiuser, usergroupid): | |
1021 """ | |
1022 Delete given user group by user group id or name. | |
1023 This command can be executed only using api_key | |
1024 belonging to user with admin rights or an admin of given user group | |
1025 | |
1026 :param apiuser: filled automatically from apikey | |
1027 :type apiuser: AuthUser | |
1028 :param usergroupid: | |
1029 :type usergroupid: int | |
1030 | |
1031 OUTPUT:: | |
1032 | |
1033 id : <id_given_in_input> | |
1034 result : { | |
1035 "msg": "deleted user group ID:<user_group_id> <user_group_name>" | |
1036 } | |
1037 error : null | |
1038 | |
1039 ERROR OUTPUT:: | |
1040 | |
1041 id : <id_given_in_input> | |
1042 result : null | |
1043 error : { | |
1044 "failed to delete user group ID:<user_group_id> <user_group_name>" | |
1045 or | |
1046 "RepoGroup assigned to <repo_groups_list>" | |
1047 } | |
1048 | |
1049 """ | |
1050 user_group = get_user_group_or_error(usergroupid) | |
1051 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | |
1052 # check if we have admin permission for this user group ! | |
1053 _perms = ('usergroup.admin',) | |
1054 if not HasUserGroupPermissionAny(*_perms)( | |
1055 user=apiuser, user_group_name=user_group.users_group_name): | |
1056 raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) | |
1057 | |
1058 try: | |
1059 UserGroupModel().delete(user_group) | |
1060 Session().commit() | |
1061 return dict( | |
1062 msg='deleted user group ID:%s %s' % | |
1063 (user_group.users_group_id, user_group.users_group_name), | |
1064 user_group=None | |
1065 ) | |
1066 except UserGroupsAssignedException, e: | |
1067 log.error(traceback.format_exc()) | |
1068 raise JSONRPCError(str(e)) | |
1069 except Exception: | |
1070 log.error(traceback.format_exc()) | |
1071 raise JSONRPCError('failed to delete user group ID:%s %s' % | |
1072 (user_group.users_group_id, | |
1073 user_group.users_group_name) | |
1074 ) | |
1075 | |
1076 # permission check inside | |
1077 def add_user_to_user_group(self, apiuser, usergroupid, userid): | |
1078 """ | |
1079 Adds a user to a user group. If user exists in that group success will be | |
1080 `false`. This command can be executed only using api_key | |
1081 belonging to user with admin rights or an admin of given user group | |
1082 | |
1083 :param apiuser: filled automatically from apikey | |
1084 :type apiuser: AuthUser | |
1085 :param usergroupid: | |
1086 :type usergroupid: int | |
630 :param userid: | 1087 :param userid: |
1088 :type userid: int | |
1089 | |
1090 OUTPUT:: | |
1091 | |
1092 id : <id_given_in_input> | |
1093 result : { | |
1094 "success": True|False # depends on if member is in group | |
1095 "msg": "added member `<username>` to user group `<groupname>` | | |
1096 User is already in that group" | |
1097 | |
1098 } | |
1099 error : null | |
1100 | |
1101 ERROR OUTPUT:: | |
1102 | |
1103 id : <id_given_in_input> | |
1104 result : null | |
1105 error : { | |
1106 "failed to add member to user group `<user_group_name>`" | |
1107 } | |
1108 | |
631 """ | 1109 """ |
632 user = get_user_or_error(userid) | 1110 user = get_user_or_error(userid) |
633 users_group = get_users_group_or_error(usersgroupid) | 1111 user_group = get_user_group_or_error(usergroupid) |
634 | 1112 if not HasPermissionAnyApi('hg.admin')(user=apiuser): |
635 try: | 1113 # check if we have admin permission for this user group ! |
636 ugm = UserGroupModel().add_user_to_group(users_group, user) | 1114 _perms = ('usergroup.admin',) |
1115 if not HasUserGroupPermissionAny(*_perms)( | |
1116 user=apiuser, user_group_name=user_group.users_group_name): | |
1117 raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) | |
1118 | |
1119 try: | |
1120 ugm = UserGroupModel().add_user_to_group(user_group, user) | |
637 success = True if ugm != True else False | 1121 success = True if ugm != True else False |
638 msg = 'added member `%s` to user group `%s`' % ( | 1122 msg = 'added member `%s` to user group `%s`' % ( |
639 user.username, users_group.users_group_name | 1123 user.username, user_group.users_group_name |
640 ) | 1124 ) |
641 msg = msg if success else 'User is already in that group' | 1125 msg = msg if success else 'User is already in that group' |
642 Session().commit() | 1126 Session().commit() |
643 | 1127 |
644 return dict( | 1128 return dict( |
645 success=success, | 1129 success=success, |
647 ) | 1131 ) |
648 except Exception: | 1132 except Exception: |
649 log.error(traceback.format_exc()) | 1133 log.error(traceback.format_exc()) |
650 raise JSONRPCError( | 1134 raise JSONRPCError( |
651 'failed to add member to user group `%s`' % ( | 1135 'failed to add member to user group `%s`' % ( |
652 users_group.users_group_name | 1136 user_group.users_group_name, |
653 ) | 1137 ) |
654 ) | 1138 ) |
655 | 1139 |
656 @HasPermissionAllDecorator('hg.admin') | 1140 # permission check inside |
657 def remove_user_from_users_group(self, apiuser, usersgroupid, userid): | 1141 def remove_user_from_user_group(self, apiuser, usergroupid, userid): |
658 """ | 1142 """ |
659 Remove user from a group | 1143 Removes a user from a user group. If user is not in given group success will |
660 | 1144 be `false`. This command can be executed only |
661 :param apiuser: | 1145 using api_key belonging to user with admin rights or an admin of given user group |
662 :param usersgroupid: | 1146 |
1147 :param apiuser: filled automatically from apikey | |
1148 :type apiuser: AuthUser | |
1149 :param usergroupid: | |
663 :param userid: | 1150 :param userid: |
1151 | |
1152 | |
1153 OUTPUT:: | |
1154 | |
1155 id : <id_given_in_input> | |
1156 result: { | |
1157 "success": True|False, # depends on if member is in group | |
1158 "msg": "removed member <username> from user group <groupname> | | |
1159 User wasn't in group" | |
1160 } | |
1161 error: null | |
1162 | |
664 """ | 1163 """ |
665 user = get_user_or_error(userid) | 1164 user = get_user_or_error(userid) |
666 users_group = get_users_group_or_error(usersgroupid) | 1165 user_group = get_user_group_or_error(usergroupid) |
667 | 1166 if not HasPermissionAnyApi('hg.admin')(user=apiuser): |
668 try: | 1167 # check if we have admin permission for this user group ! |
669 success = UserGroupModel().remove_user_from_group(users_group, | 1168 _perms = ('usergroup.admin',) |
670 user) | 1169 if not HasUserGroupPermissionAny(*_perms)( |
1170 user=apiuser, user_group_name=user_group.users_group_name): | |
1171 raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) | |
1172 | |
1173 try: | |
1174 success = UserGroupModel().remove_user_from_group(user_group, user) | |
671 msg = 'removed member `%s` from user group `%s`' % ( | 1175 msg = 'removed member `%s` from user group `%s`' % ( |
672 user.username, users_group.users_group_name | 1176 user.username, user_group.users_group_name |
673 ) | 1177 ) |
674 msg = msg if success else "User wasn't in group" | 1178 msg = msg if success else "User wasn't in group" |
675 Session().commit() | 1179 Session().commit() |
676 return dict(success=success, msg=msg) | 1180 return dict(success=success, msg=msg) |
677 except Exception: | 1181 except Exception: |
678 log.error(traceback.format_exc()) | 1182 log.error(traceback.format_exc()) |
679 raise JSONRPCError( | 1183 raise JSONRPCError( |
680 'failed to remove member from user group `%s`' % ( | 1184 'failed to remove member from user group `%s`' % ( |
681 users_group.users_group_name | 1185 user_group.users_group_name, |
682 ) | 1186 ) |
683 ) | 1187 ) |
684 | 1188 |
1189 # permission check inside | |
685 def get_repo(self, apiuser, repoid): | 1190 def get_repo(self, apiuser, repoid): |
686 """" | 1191 """ |
687 Get repository by name | 1192 Gets an existing repository by it's name or repository_id. Members will return |
688 | 1193 either users_group or user associated to that repository. This command can be |
689 :param apiuser: | 1194 executed only using api_key belonging to user with admin |
690 :param repoid: | 1195 rights or regular user that have at least read access to repository. |
1196 | |
1197 :param apiuser: filled automatically from apikey | |
1198 :type apiuser: AuthUser | |
1199 :param repoid: repository name or repository id | |
1200 :type repoid: str or int | |
1201 | |
1202 OUTPUT:: | |
1203 | |
1204 id : <id_given_in_input> | |
1205 result : { | |
1206 { | |
1207 "repo_id" : "<repo_id>", | |
1208 "repo_name" : "<reponame>" | |
1209 "repo_type" : "<repo_type>", | |
1210 "clone_uri" : "<clone_uri>", | |
1211 "enable_downloads": "<bool>", | |
1212 "enable_locking": "<bool>", | |
1213 "enable_statistics": "<bool>", | |
1214 "private": "<bool>", | |
1215 "created_on" : "<date_time_created>", | |
1216 "description" : "<description>", | |
1217 "landing_rev": "<landing_rev>", | |
1218 "last_changeset": { | |
1219 "author": "<full_author>", | |
1220 "date": "<date_time_of_commit>", | |
1221 "message": "<commit_message>", | |
1222 "raw_id": "<raw_id>", | |
1223 "revision": "<numeric_revision>", | |
1224 "short_id": "<short_id>" | |
1225 } | |
1226 "owner": "<repo_owner>", | |
1227 "fork_of": "<name_of_fork_parent>", | |
1228 "members" : [ | |
1229 { | |
1230 "name": "<username>", | |
1231 "type" : "user", | |
1232 "permission" : "repository.(read|write|admin)" | |
1233 }, | |
1234 โฆ | |
1235 { | |
1236 "name": "<usergroup name>", | |
1237 "type" : "user_group", | |
1238 "permission" : "usergroup.(read|write|admin)" | |
1239 }, | |
1240 โฆ | |
1241 ] | |
1242 "followers": [<user_obj>, ...] | |
1243 ] | |
1244 } | |
1245 } | |
1246 error : null | |
1247 | |
691 """ | 1248 """ |
692 repo = get_repo_or_error(repoid) | 1249 repo = get_repo_or_error(repoid) |
693 | 1250 |
694 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | 1251 if not HasPermissionAnyApi('hg.admin')(user=apiuser): |
695 # check if we have admin permission for this repo ! | 1252 # check if we have admin permission for this repo ! |
696 if not HasRepoPermissionAnyApi('repository.admin')(user=apiuser, | 1253 perms = ('repository.admin', 'repository.write', 'repository.read') |
697 repo_name=repo.repo_name): | 1254 if not HasRepoPermissionAnyApi(*perms)(user=apiuser, repo_name=repo.repo_name): |
698 raise JSONRPCError('repository `%s` does not exist' % (repoid)) | 1255 raise JSONRPCError('repository `%s` does not exist' % (repoid,)) |
699 | 1256 |
700 members = [] | 1257 members = [] |
701 followers = [] | 1258 followers = [] |
702 for user in repo.repo_to_perm: | 1259 for user in repo.repo_to_perm: |
703 perm = user.permission.permission_name | 1260 perm = user.permission.permission_name |
704 user = user.user | 1261 user = user.user |
705 user_data = user.get_api_data() | 1262 user_data = { |
706 user_data['type'] = "user" | 1263 'name': user.username, |
707 user_data['permission'] = perm | 1264 'type': "user", |
1265 'permission': perm | |
1266 } | |
708 members.append(user_data) | 1267 members.append(user_data) |
709 | 1268 |
710 for users_group in repo.users_group_to_perm: | 1269 for user_group in repo.users_group_to_perm: |
711 perm = users_group.permission.permission_name | 1270 perm = user_group.permission.permission_name |
712 users_group = users_group.users_group | 1271 user_group = user_group.users_group |
713 users_group_data = users_group.get_api_data() | 1272 user_group_data = { |
714 users_group_data['type'] = "users_group" | 1273 'name': user_group.users_group_name, |
715 users_group_data['permission'] = perm | 1274 'type': "user_group", |
716 members.append(users_group_data) | 1275 'permission': perm |
1276 } | |
1277 members.append(user_group_data) | |
717 | 1278 |
718 for user in repo.followers: | 1279 for user in repo.followers: |
719 followers.append(user.user.get_api_data()) | 1280 followers.append(user.user.get_api_data()) |
720 | 1281 |
721 data = repo.get_api_data() | 1282 data = repo.get_api_data() |
723 data['followers'] = followers | 1284 data['followers'] = followers |
724 return data | 1285 return data |
725 | 1286 |
726 # permission check inside | 1287 # permission check inside |
727 def get_repos(self, apiuser): | 1288 def get_repos(self, apiuser): |
728 """" | 1289 """ |
729 Get all repositories | 1290 Lists all existing repositories. This command can be executed only using |
730 | 1291 api_key belonging to user with admin rights or regular user that have |
731 :param apiuser: | 1292 admin, write or read access to repository. |
1293 | |
1294 :param apiuser: filled automatically from apikey | |
1295 :type apiuser: AuthUser | |
1296 | |
1297 OUTPUT:: | |
1298 | |
1299 id : <id_given_in_input> | |
1300 result: [ | |
1301 { | |
1302 "repo_id" : "<repo_id>", | |
1303 "repo_name" : "<reponame>" | |
1304 "repo_type" : "<repo_type>", | |
1305 "clone_uri" : "<clone_uri>", | |
1306 "private": : "<bool>", | |
1307 "created_on" : "<datetimecreated>", | |
1308 "description" : "<description>", | |
1309 "landing_rev": "<landing_rev>", | |
1310 "owner": "<repo_owner>", | |
1311 "fork_of": "<name_of_fork_parent>", | |
1312 "enable_downloads": "<bool>", | |
1313 "enable_locking": "<bool>", | |
1314 "enable_statistics": "<bool>", | |
1315 }, | |
1316 โฆ | |
1317 ] | |
1318 error: null | |
732 """ | 1319 """ |
733 result = [] | 1320 result = [] |
734 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False: | 1321 if not HasPermissionAnyApi('hg.admin')(user=apiuser): |
735 repos = RepoModel().get_all_user_repos(user=apiuser) | 1322 repos = RepoModel().get_all_user_repos(user=apiuser) |
736 else: | 1323 else: |
737 repos = RepoModel().get_all() | 1324 repos = RepoModel().get_all() |
738 | 1325 |
739 for repo in repos: | 1326 for repo in repos: |
740 result.append(repo.get_api_data()) | 1327 result.append(repo.get_api_data()) |
741 return result | 1328 return result |
742 | 1329 |
743 @HasPermissionAllDecorator('hg.admin') | 1330 # permission check inside |
744 def get_repo_nodes(self, apiuser, repoid, revision, root_path, | 1331 def get_repo_nodes(self, apiuser, repoid, revision, root_path, |
745 ret_type='all'): | 1332 ret_type=Optional('all')): |
746 """ | 1333 """ |
747 returns a list of nodes and it's children | 1334 returns a list of nodes and it's children in a flat list for a given path |
748 for a given path at given revision. It's possible to specify ret_type | 1335 at given revision. It's possible to specify ret_type to show only `files` or |
749 to show only files or dirs | 1336 `dirs`. This command can be executed only using api_key belonging to |
750 | 1337 user with admin rights or regular user that have at least read access to repository. |
751 :param apiuser: | 1338 |
752 :param repoid: name or id of repository | 1339 :param apiuser: filled automatically from apikey |
1340 :type apiuser: AuthUser | |
1341 :param repoid: repository name or repository id | |
1342 :type repoid: str or int | |
753 :param revision: revision for which listing should be done | 1343 :param revision: revision for which listing should be done |
1344 :type revision: str | |
754 :param root_path: path from which start displaying | 1345 :param root_path: path from which start displaying |
1346 :type root_path: str | |
755 :param ret_type: return type 'all|files|dirs' nodes | 1347 :param ret_type: return type 'all|files|dirs' nodes |
1348 :type ret_type: Optional(str) | |
1349 | |
1350 | |
1351 OUTPUT:: | |
1352 | |
1353 id : <id_given_in_input> | |
1354 result: [ | |
1355 { | |
1356 "name" : "<name>" | |
1357 "type" : "<type>", | |
1358 }, | |
1359 โฆ | |
1360 ] | |
1361 error: null | |
756 """ | 1362 """ |
757 repo = get_repo_or_error(repoid) | 1363 repo = get_repo_or_error(repoid) |
1364 | |
1365 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | |
1366 # check if we have admin permission for this repo ! | |
1367 perms = ('repository.admin', 'repository.write', 'repository.read') | |
1368 if not HasRepoPermissionAnyApi(*perms)(user=apiuser, repo_name=repo.repo_name): | |
1369 raise JSONRPCError('repository `%s` does not exist' % (repoid,)) | |
1370 | |
1371 ret_type = Optional.extract(ret_type) | |
1372 _map = {} | |
758 try: | 1373 try: |
759 _d, _f = ScmModel().get_nodes(repo, revision, root_path, | 1374 _d, _f = ScmModel().get_nodes(repo, revision, root_path, |
760 flat=False) | 1375 flat=False) |
761 _map = { | 1376 _map = { |
762 'all': _d + _f, | 1377 'all': _d + _f, |
763 'files': _f, | 1378 'files': _f, |
764 'dirs': _d, | 1379 'dirs': _d, |
765 } | 1380 } |
766 return _map[ret_type] | 1381 return _map[ret_type] |
767 except KeyError: | 1382 except KeyError: |
768 raise JSONRPCError('ret_type must be one of %s' % _map.keys()) | 1383 raise JSONRPCError('ret_type must be one of %s' |
1384 % (','.join(_map.keys()))) | |
769 except Exception: | 1385 except Exception: |
770 log.error(traceback.format_exc()) | 1386 log.error(traceback.format_exc()) |
771 raise JSONRPCError( | 1387 raise JSONRPCError( |
772 'failed to get repo: `%s` nodes' % repo.repo_name | 1388 'failed to get repo: `%s` nodes' % repo.repo_name |
773 ) | 1389 ) |
774 | 1390 |
775 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository') | 1391 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository') |
776 def create_repo(self, apiuser, repo_name, owner=Optional(OAttr('apiuser')), | 1392 def create_repo(self, apiuser, repo_name, owner=Optional(OAttr('apiuser')), |
777 repo_type=Optional('hg'), | 1393 repo_type=Optional('hg'), description=Optional(''), |
778 description=Optional(''), private=Optional(False), | 1394 private=Optional(False), clone_uri=Optional(None), |
779 clone_uri=Optional(None), landing_rev=Optional('tip'), | 1395 landing_rev=Optional('rev:tip'), |
780 enable_statistics=Optional(False), | 1396 enable_statistics=Optional(False), |
781 enable_locking=Optional(False), | 1397 enable_locking=Optional(False), |
782 enable_downloads=Optional(False)): | 1398 enable_downloads=Optional(False), |
783 """ | 1399 copy_permissions=Optional(False)): |
784 Create repository, if clone_url is given it makes a remote clone | 1400 """ |
785 if repo_name is within a group name the groups will be created | 1401 Creates a repository. If repository name contains "/", all needed repository |
786 automatically if they aren't present | 1402 groups will be created. For example "foo/bar/baz" will create groups |
787 | 1403 "foo", "bar" (with "foo" as parent), and create "baz" repository with |
788 :param apiuser: | 1404 "bar" as group. This command can be executed only using api_key |
789 :param repo_name: | 1405 belonging to user with admin rights or regular user that have create |
790 :param onwer: | 1406 repository permission. Regular users cannot specify owner parameter |
791 :param repo_type: | 1407 |
792 :param description: | 1408 :param apiuser: filled automatically from apikey |
1409 :type apiuser: AuthUser | |
1410 :param repo_name: repository name | |
1411 :type repo_name: str | |
1412 :param owner: user_id or username | |
1413 :type owner: Optional(str) | |
1414 :param repo_type: 'hg' or 'git' | |
1415 :type repo_type: Optional(str) | |
1416 :param description: repository description | |
1417 :type description: Optional(str) | |
793 :param private: | 1418 :param private: |
1419 :type private: bool | |
794 :param clone_uri: | 1420 :param clone_uri: |
795 :param landing_rev: | 1421 :type clone_uri: str |
796 """ | 1422 :param landing_rev: <rev_type>:<rev> |
797 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False: | 1423 :type landing_rev: str |
1424 :param enable_locking: | |
1425 :type enable_locking: bool | |
1426 :param enable_downloads: | |
1427 :type enable_downloads: bool | |
1428 :param enable_statistics: | |
1429 :type enable_statistics: bool | |
1430 :param copy_permissions: Copy permission from group that repository is | |
1431 beeing created. | |
1432 :type copy_permissions: bool | |
1433 | |
1434 OUTPUT:: | |
1435 | |
1436 id : <id_given_in_input> | |
1437 result: { | |
1438 "msg": "Created new repository `<reponame>`", | |
1439 "success": true, | |
1440 "task": "<celery task id or None if done sync>" | |
1441 } | |
1442 error: null | |
1443 | |
1444 ERROR OUTPUT:: | |
1445 | |
1446 id : <id_given_in_input> | |
1447 result : null | |
1448 error : { | |
1449 'failed to create repository `<repo_name>` | |
1450 } | |
1451 | |
1452 """ | |
1453 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | |
798 if not isinstance(owner, Optional): | 1454 if not isinstance(owner, Optional): |
799 #forbid setting owner for non-admins | 1455 #forbid setting owner for non-admins |
800 raise JSONRPCError( | 1456 raise JSONRPCError( |
801 'Only RhodeCode admin can specify `owner` param' | 1457 'Only RhodeCode admin can specify `owner` param' |
802 ) | 1458 ) |
821 enable_downloads = defs.get('repo_enable_downloads') | 1477 enable_downloads = defs.get('repo_enable_downloads') |
822 | 1478 |
823 clone_uri = Optional.extract(clone_uri) | 1479 clone_uri = Optional.extract(clone_uri) |
824 description = Optional.extract(description) | 1480 description = Optional.extract(description) |
825 landing_rev = Optional.extract(landing_rev) | 1481 landing_rev = Optional.extract(landing_rev) |
826 | 1482 copy_permissions = Optional.extract(copy_permissions) |
827 try: | 1483 |
1484 try: | |
1485 repo_name_cleaned = repo_name.split('/')[-1] | |
828 # create structure of groups and return the last group | 1486 # create structure of groups and return the last group |
829 group = map_groups(repo_name) | 1487 repo_group = map_groups(repo_name) |
830 | 1488 data = dict( |
831 repo = RepoModel().create_repo( | 1489 repo_name=repo_name_cleaned, |
832 repo_name=repo_name, | 1490 repo_name_full=repo_name, |
833 repo_type=repo_type, | 1491 repo_type=repo_type, |
834 description=description, | 1492 repo_description=description, |
835 owner=owner, | 1493 owner=owner, |
836 private=private, | 1494 repo_private=private, |
837 clone_uri=clone_uri, | 1495 clone_uri=clone_uri, |
838 repos_group=group, | 1496 repo_group=repo_group, |
839 landing_rev=landing_rev, | 1497 repo_landing_rev=landing_rev, |
840 enable_statistics=enable_statistics, | 1498 enable_statistics=enable_statistics, |
1499 enable_locking=enable_locking, | |
841 enable_downloads=enable_downloads, | 1500 enable_downloads=enable_downloads, |
842 enable_locking=enable_locking | 1501 repo_copy_permissions=copy_permissions, |
843 ) | 1502 ) |
844 | 1503 |
845 Session().commit() | 1504 task = RepoModel().create(form_data=data, cur_user=owner) |
1505 from celery.result import BaseAsyncResult | |
1506 task_id = None | |
1507 if isinstance(task, BaseAsyncResult): | |
1508 task_id = task.task_id | |
1509 # no commit, it's done in RepoModel, or async via celery | |
846 return dict( | 1510 return dict( |
847 msg="Created new repository `%s`" % (repo.repo_name), | 1511 msg="Created new repository `%s`" % (repo_name,), |
848 repo=repo.get_api_data() | 1512 success=True, # cannot return the repo data here since fork |
849 ) | 1513 # cann be done async |
850 except Exception: | 1514 task=task_id |
851 log.error(traceback.format_exc()) | 1515 ) |
852 raise JSONRPCError('failed to create repository `%s`' % repo_name) | 1516 except Exception: |
1517 log.error(traceback.format_exc()) | |
1518 raise JSONRPCError( | |
1519 'failed to create repository `%s`' % (repo_name,)) | |
853 | 1520 |
854 # permission check inside | 1521 # permission check inside |
855 def update_repo(self, apiuser, repoid, name=Optional(None), | 1522 def update_repo(self, apiuser, repoid, name=Optional(None), |
856 owner=Optional(OAttr('apiuser')), | 1523 owner=Optional(OAttr('apiuser')), |
857 group=Optional(None), | 1524 group=Optional(None), |
858 description=Optional(''), private=Optional(False), | 1525 description=Optional(''), private=Optional(False), |
859 clone_uri=Optional(None), landing_rev=Optional('tip'), | 1526 clone_uri=Optional(None), landing_rev=Optional('rev:tip'), |
860 enable_statistics=Optional(False), | 1527 enable_statistics=Optional(False), |
861 enable_locking=Optional(False), | 1528 enable_locking=Optional(False), |
862 enable_downloads=Optional(False)): | 1529 enable_downloads=Optional(False)): |
863 | 1530 |
864 """ | 1531 """ |
915 except Exception: | 1582 except Exception: |
916 log.error(traceback.format_exc()) | 1583 log.error(traceback.format_exc()) |
917 raise JSONRPCError('failed to update repo `%s`' % repoid) | 1584 raise JSONRPCError('failed to update repo `%s`' % repoid) |
918 | 1585 |
919 @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository') | 1586 @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository') |
920 def fork_repo(self, apiuser, repoid, fork_name, owner=Optional(OAttr('apiuser')), | 1587 def fork_repo(self, apiuser, repoid, fork_name, |
1588 owner=Optional(OAttr('apiuser')), | |
921 description=Optional(''), copy_permissions=Optional(False), | 1589 description=Optional(''), copy_permissions=Optional(False), |
922 private=Optional(False), landing_rev=Optional('tip')): | 1590 private=Optional(False), landing_rev=Optional('rev:tip')): |
1591 """ | |
1592 Creates a fork of given repo. In case of using celery this will | |
1593 immidiatelly return success message, while fork is going to be created | |
1594 asynchronous. This command can be executed only using api_key belonging to | |
1595 user with admin rights or regular user that have fork permission, and at least | |
1596 read access to forking repository. Regular users cannot specify owner parameter. | |
1597 | |
1598 :param apiuser: filled automatically from apikey | |
1599 :type apiuser: AuthUser | |
1600 :param repoid: repository name or repository id | |
1601 :type repoid: str or int | |
1602 :param fork_name: | |
1603 :param owner: | |
1604 :param description: | |
1605 :param copy_permissions: | |
1606 :param private: | |
1607 :param landing_rev: | |
1608 | |
1609 INPUT:: | |
1610 | |
1611 id : <id_for_response> | |
1612 api_key : "<api_key>" | |
1613 args: { | |
1614 "repoid" : "<reponame or repo_id>", | |
1615 "fork_name": "<forkname>", | |
1616 "owner": "<username or user_id = Optional(=apiuser)>", | |
1617 "description": "<description>", | |
1618 "copy_permissions": "<bool>", | |
1619 "private": "<bool>", | |
1620 "landing_rev": "<landing_rev>" | |
1621 } | |
1622 | |
1623 OUTPUT:: | |
1624 | |
1625 id : <id_given_in_input> | |
1626 result: { | |
1627 "msg": "Created fork of `<reponame>` as `<forkname>`", | |
1628 "success": true, | |
1629 "task": "<celery task id or None if done sync>" | |
1630 } | |
1631 error: null | |
1632 | |
1633 """ | |
923 repo = get_repo_or_error(repoid) | 1634 repo = get_repo_or_error(repoid) |
924 repo_name = repo.repo_name | 1635 repo_name = repo.repo_name |
925 | 1636 |
926 _repo = RepoModel().get_by_repo_name(fork_name) | 1637 _repo = RepoModel().get_by_repo_name(fork_name) |
927 if _repo: | 1638 if _repo: |
938 #forbid setting owner for non-admins | 1649 #forbid setting owner for non-admins |
939 raise JSONRPCError( | 1650 raise JSONRPCError( |
940 'Only RhodeCode admin can specify `owner` param' | 1651 'Only RhodeCode admin can specify `owner` param' |
941 ) | 1652 ) |
942 else: | 1653 else: |
943 raise JSONRPCError('repository `%s` does not exist' % (repoid)) | 1654 raise JSONRPCError('repository `%s` does not exist' % (repoid,)) |
944 | 1655 |
945 if isinstance(owner, Optional): | 1656 if isinstance(owner, Optional): |
946 owner = apiuser.user_id | 1657 owner = apiuser.user_id |
947 | 1658 |
948 owner = get_user_or_error(owner) | 1659 owner = get_user_or_error(owner) |
961 copy_permissions=Optional.extract(copy_permissions), | 1672 copy_permissions=Optional.extract(copy_permissions), |
962 landing_rev=Optional.extract(landing_rev), | 1673 landing_rev=Optional.extract(landing_rev), |
963 update_after_clone=False, | 1674 update_after_clone=False, |
964 fork_parent_id=repo.repo_id, | 1675 fork_parent_id=repo.repo_id, |
965 ) | 1676 ) |
966 RepoModel().create_fork(form_data, cur_user=owner) | 1677 task = RepoModel().create_fork(form_data, cur_user=owner) |
1678 # no commit, it's done in RepoModel, or async via celery | |
1679 from celery.result import BaseAsyncResult | |
1680 task_id = None | |
1681 if isinstance(task, BaseAsyncResult): | |
1682 task_id = task.task_id | |
967 return dict( | 1683 return dict( |
968 msg='Created fork of `%s` as `%s`' % (repo.repo_name, | 1684 msg='Created fork of `%s` as `%s`' % (repo.repo_name, |
969 fork_name), | 1685 fork_name), |
970 success=True # cannot return the repo data here since fork | 1686 success=True, # cannot return the repo data here since fork |
971 # cann be done async | 1687 # cann be done async |
1688 task=task_id | |
972 ) | 1689 ) |
973 except Exception: | 1690 except Exception: |
974 log.error(traceback.format_exc()) | 1691 log.error(traceback.format_exc()) |
975 raise JSONRPCError( | 1692 raise JSONRPCError( |
976 'failed to fork repository `%s` as `%s`' % (repo_name, | 1693 'failed to fork repository `%s` as `%s`' % (repo_name, |
977 fork_name) | 1694 fork_name) |
978 ) | 1695 ) |
979 | 1696 |
980 # perms handled inside | 1697 # permission check inside |
981 def delete_repo(self, apiuser, repoid, forks=Optional(None)): | 1698 def delete_repo(self, apiuser, repoid, forks=Optional('')): |
982 """ | 1699 """ |
983 Deletes a given repository | 1700 Deletes a repository. This command can be executed only using api_key belonging |
984 | 1701 to user with admin rights or regular user that have admin access to repository. |
985 :param apiuser: | 1702 When `forks` param is set it's possible to detach or delete forks of deleting |
986 :param repoid: | 1703 repository |
987 :param forks: detach or delete, what do do with attached forks for repo | 1704 |
1705 :param apiuser: filled automatically from apikey | |
1706 :type apiuser: AuthUser | |
1707 :param repoid: repository name or repository id | |
1708 :type repoid: str or int | |
1709 :param forks: `detach` or `delete`, what do do with attached forks for repo | |
1710 :type forks: Optional(str) | |
1711 | |
1712 OUTPUT:: | |
1713 | |
1714 id : <id_given_in_input> | |
1715 result: { | |
1716 "msg": "Deleted repository `<reponame>`", | |
1717 "success": true | |
1718 } | |
1719 error: null | |
1720 | |
988 """ | 1721 """ |
989 repo = get_repo_or_error(repoid) | 1722 repo = get_repo_or_error(repoid) |
990 | 1723 |
991 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False: | 1724 if not HasPermissionAnyApi('hg.admin')(user=apiuser): |
992 # check if we have admin permission for this repo ! | 1725 # check if we have admin permission for this repo ! |
993 if HasRepoPermissionAnyApi('repository.admin')(user=apiuser, | 1726 if not HasRepoPermissionAnyApi('repository.admin')(user=apiuser, |
994 repo_name=repo.repo_name) is False: | 1727 repo_name=repo.repo_name): |
995 raise JSONRPCError('repository `%s` does not exist' % (repoid)) | 1728 raise JSONRPCError('repository `%s` does not exist' % (repoid,)) |
996 | 1729 |
997 try: | 1730 try: |
998 handle_forks = Optional.extract(forks) | 1731 handle_forks = Optional.extract(forks) |
999 _forks_msg = '' | 1732 _forks_msg = '' |
1000 _forks = [f for f in repo.forks] | 1733 _forks = [f for f in repo.forks] |
1002 _forks_msg = ' ' + 'Detached %s forks' % len(_forks) | 1735 _forks_msg = ' ' + 'Detached %s forks' % len(_forks) |
1003 elif handle_forks == 'delete': | 1736 elif handle_forks == 'delete': |
1004 _forks_msg = ' ' + 'Deleted %s forks' % len(_forks) | 1737 _forks_msg = ' ' + 'Deleted %s forks' % len(_forks) |
1005 elif _forks: | 1738 elif _forks: |
1006 raise JSONRPCError( | 1739 raise JSONRPCError( |
1007 'Cannot delete `%s` it still contains attached forks' | 1740 'Cannot delete `%s` it still contains attached forks' % |
1008 % repo.repo_name | 1741 (repo.repo_name,) |
1009 ) | 1742 ) |
1010 | 1743 |
1011 RepoModel().delete(repo, forks=forks) | 1744 RepoModel().delete(repo, forks=forks) |
1012 Session().commit() | 1745 Session().commit() |
1013 return dict( | 1746 return dict( |
1015 success=True | 1748 success=True |
1016 ) | 1749 ) |
1017 except Exception: | 1750 except Exception: |
1018 log.error(traceback.format_exc()) | 1751 log.error(traceback.format_exc()) |
1019 raise JSONRPCError( | 1752 raise JSONRPCError( |
1020 'failed to delete repository `%s`' % repo.repo_name | 1753 'failed to delete repository `%s`' % (repo.repo_name,) |
1021 ) | 1754 ) |
1022 | 1755 |
1023 @HasPermissionAllDecorator('hg.admin') | 1756 @HasPermissionAllDecorator('hg.admin') |
1024 def grant_user_permission(self, apiuser, repoid, userid, perm): | 1757 def grant_user_permission(self, apiuser, repoid, userid, perm): |
1025 """ | 1758 """ |
1026 Grant permission for user on given repository, or update existing one | 1759 Grant permission for user on given repository, or update existing one |
1027 if found | 1760 if found. This command can be executed only using api_key belonging to user |
1028 | 1761 with admin rights. |
1029 :param repoid: | 1762 |
1763 :param apiuser: filled automatically from apikey | |
1764 :type apiuser: AuthUser | |
1765 :param repoid: repository name or repository id | |
1766 :type repoid: str or int | |
1030 :param userid: | 1767 :param userid: |
1031 :param perm: | 1768 :param perm: (repository.(none|read|write|admin)) |
1769 :type perm: str | |
1770 | |
1771 OUTPUT:: | |
1772 | |
1773 id : <id_given_in_input> | |
1774 result: { | |
1775 "msg" : "Granted perm: `<perm>` for user: `<username>` in repo: `<reponame>`", | |
1776 "success": true | |
1777 } | |
1778 error: null | |
1032 """ | 1779 """ |
1033 repo = get_repo_or_error(repoid) | 1780 repo = get_repo_or_error(repoid) |
1034 user = get_user_or_error(userid) | 1781 user = get_user_or_error(userid) |
1035 perm = get_perm_or_error(perm) | 1782 perm = get_perm_or_error(perm) |
1036 | 1783 |
1054 ) | 1801 ) |
1055 | 1802 |
1056 @HasPermissionAllDecorator('hg.admin') | 1803 @HasPermissionAllDecorator('hg.admin') |
1057 def revoke_user_permission(self, apiuser, repoid, userid): | 1804 def revoke_user_permission(self, apiuser, repoid, userid): |
1058 """ | 1805 """ |
1059 Revoke permission for user on given repository | 1806 Revoke permission for user on given repository. This command can be executed |
1060 | 1807 only using api_key belonging to user with admin rights. |
1061 :param apiuser: | 1808 |
1062 :param repoid: | 1809 :param apiuser: filled automatically from apikey |
1810 :type apiuser: AuthUser | |
1811 :param repoid: repository name or repository id | |
1812 :type repoid: str or int | |
1063 :param userid: | 1813 :param userid: |
1814 | |
1815 OUTPUT:: | |
1816 | |
1817 id : <id_given_in_input> | |
1818 result: { | |
1819 "msg" : "Revoked perm for user: `<username>` in repo: `<reponame>`", | |
1820 "success": true | |
1821 } | |
1822 error: null | |
1823 | |
1064 """ | 1824 """ |
1065 | 1825 |
1066 repo = get_repo_or_error(repoid) | 1826 repo = get_repo_or_error(repoid) |
1067 user = get_user_or_error(userid) | 1827 user = get_user_or_error(userid) |
1068 try: | 1828 try: |
1069 | |
1070 RepoModel().revoke_user_permission(repo=repo, user=user) | 1829 RepoModel().revoke_user_permission(repo=repo, user=user) |
1071 | |
1072 Session().commit() | 1830 Session().commit() |
1073 return dict( | 1831 return dict( |
1074 msg='Revoked perm for user: `%s` in repo: `%s`' % ( | 1832 msg='Revoked perm for user: `%s` in repo: `%s`' % ( |
1075 user.username, repo.repo_name | 1833 user.username, repo.repo_name |
1076 ), | 1834 ), |
1082 'failed to edit permission for user: `%s` in repo: `%s`' % ( | 1840 'failed to edit permission for user: `%s` in repo: `%s`' % ( |
1083 userid, repoid | 1841 userid, repoid |
1084 ) | 1842 ) |
1085 ) | 1843 ) |
1086 | 1844 |
1087 @HasPermissionAllDecorator('hg.admin') | 1845 # permission check inside |
1088 def grant_users_group_permission(self, apiuser, repoid, usersgroupid, | 1846 def grant_user_group_permission(self, apiuser, repoid, usergroupid, perm): |
1089 perm): | |
1090 """ | 1847 """ |
1091 Grant permission for user group on given repository, or update | 1848 Grant permission for user group on given repository, or update |
1092 existing one if found | 1849 existing one if found. This command can be executed only using |
1093 | 1850 api_key belonging to user with admin rights. |
1094 :param apiuser: | 1851 |
1095 :param repoid: | 1852 :param apiuser: filled automatically from apikey |
1096 :param usersgroupid: | 1853 :type apiuser: AuthUser |
1097 :param perm: | 1854 :param repoid: repository name or repository id |
1855 :type repoid: str or int | |
1856 :param usergroupid: id of usergroup | |
1857 :type usergroupid: str or int | |
1858 :param perm: (repository.(none|read|write|admin)) | |
1859 :type perm: str | |
1860 | |
1861 OUTPUT:: | |
1862 | |
1863 id : <id_given_in_input> | |
1864 result : { | |
1865 "msg" : "Granted perm: `<perm>` for group: `<usersgroupname>` in repo: `<reponame>`", | |
1866 "success": true | |
1867 | |
1868 } | |
1869 error : null | |
1870 | |
1871 ERROR OUTPUT:: | |
1872 | |
1873 id : <id_given_in_input> | |
1874 result : null | |
1875 error : { | |
1876 "failed to edit permission for user group: `<usergroup>` in repo `<repo>`' | |
1877 } | |
1878 | |
1098 """ | 1879 """ |
1099 repo = get_repo_or_error(repoid) | 1880 repo = get_repo_or_error(repoid) |
1100 perm = get_perm_or_error(perm) | 1881 perm = get_perm_or_error(perm) |
1101 users_group = get_users_group_or_error(usersgroupid) | 1882 user_group = get_user_group_or_error(usergroupid) |
1102 | 1883 if not HasPermissionAnyApi('hg.admin')(user=apiuser): |
1103 try: | 1884 # check if we have admin permission for this repo ! |
1104 RepoModel().grant_users_group_permission(repo=repo, | 1885 _perms = ('repository.admin',) |
1105 group_name=users_group, | 1886 if not HasRepoPermissionAnyApi(*_perms)( |
1106 perm=perm) | 1887 user=apiuser, repo_name=repo.repo_name): |
1888 raise JSONRPCError('repository `%s` does not exist' % (repoid,)) | |
1889 | |
1890 # check if we have at least read permission for this user group ! | |
1891 _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',) | |
1892 if not HasUserGroupPermissionAny(*_perms)( | |
1893 user=apiuser, user_group_name=user_group.users_group_name): | |
1894 raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) | |
1895 | |
1896 try: | |
1897 RepoModel().grant_user_group_permission( | |
1898 repo=repo, group_name=user_group, perm=perm) | |
1107 | 1899 |
1108 Session().commit() | 1900 Session().commit() |
1109 return dict( | 1901 return dict( |
1110 msg='Granted perm: `%s` for user group: `%s` in ' | 1902 msg='Granted perm: `%s` for user group: `%s` in ' |
1111 'repo: `%s`' % ( | 1903 'repo: `%s`' % ( |
1112 perm.permission_name, users_group.users_group_name, | 1904 perm.permission_name, user_group.users_group_name, |
1113 repo.repo_name | 1905 repo.repo_name |
1114 ), | 1906 ), |
1115 success=True | 1907 success=True |
1116 ) | 1908 ) |
1117 except Exception: | 1909 except Exception: |
1118 log.error(traceback.format_exc()) | 1910 log.error(traceback.format_exc()) |
1119 raise JSONRPCError( | 1911 raise JSONRPCError( |
1120 'failed to edit permission for user group: `%s` in ' | 1912 'failed to edit permission for user group: `%s` in ' |
1121 'repo: `%s`' % ( | 1913 'repo: `%s`' % ( |
1122 usersgroupid, repo.repo_name | 1914 usergroupid, repo.repo_name |
1123 ) | 1915 ) |
1124 ) | 1916 ) |
1125 | 1917 |
1126 @HasPermissionAllDecorator('hg.admin') | 1918 # permission check inside |
1127 def revoke_users_group_permission(self, apiuser, repoid, usersgroupid): | 1919 def revoke_user_group_permission(self, apiuser, repoid, usergroupid): |
1128 """ | 1920 """ |
1129 Revoke permission for user group on given repository | 1921 Revoke permission for user group on given repository. This command can be |
1130 | 1922 executed only using api_key belonging to user with admin rights. |
1131 :param apiuser: | 1923 |
1132 :param repoid: | 1924 :param apiuser: filled automatically from apikey |
1133 :param usersgroupid: | 1925 :type apiuser: AuthUser |
1926 :param repoid: repository name or repository id | |
1927 :type repoid: str or int | |
1928 :param usergroupid: | |
1929 | |
1930 OUTPUT:: | |
1931 | |
1932 id : <id_given_in_input> | |
1933 result: { | |
1934 "msg" : "Revoked perm for group: `<usersgroupname>` in repo: `<reponame>`", | |
1935 "success": true | |
1936 } | |
1937 error: null | |
1134 """ | 1938 """ |
1135 repo = get_repo_or_error(repoid) | 1939 repo = get_repo_or_error(repoid) |
1136 users_group = get_users_group_or_error(usersgroupid) | 1940 user_group = get_user_group_or_error(usergroupid) |
1137 | 1941 if not HasPermissionAnyApi('hg.admin')(user=apiuser): |
1138 try: | 1942 # check if we have admin permission for this repo ! |
1139 RepoModel().revoke_users_group_permission(repo=repo, | 1943 _perms = ('repository.admin',) |
1140 group_name=users_group) | 1944 if not HasRepoPermissionAnyApi(*_perms)( |
1945 user=apiuser, repo_name=repo.repo_name): | |
1946 raise JSONRPCError('repository `%s` does not exist' % (repoid,)) | |
1947 | |
1948 # check if we have at least read permission for this user group ! | |
1949 _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',) | |
1950 if not HasUserGroupPermissionAny(*_perms)( | |
1951 user=apiuser, user_group_name=user_group.users_group_name): | |
1952 raise JSONRPCError('user group `%s` does not exist' % (usergroupid,)) | |
1953 | |
1954 try: | |
1955 RepoModel().revoke_user_group_permission( | |
1956 repo=repo, group_name=user_group) | |
1141 | 1957 |
1142 Session().commit() | 1958 Session().commit() |
1143 return dict( | 1959 return dict( |
1144 msg='Revoked perm for user group: `%s` in repo: `%s`' % ( | 1960 msg='Revoked perm for user group: `%s` in repo: `%s`' % ( |
1145 users_group.users_group_name, repo.repo_name | 1961 user_group.users_group_name, repo.repo_name |
1146 ), | 1962 ), |
1147 success=True | 1963 success=True |
1148 ) | 1964 ) |
1149 except Exception: | 1965 except Exception: |
1150 log.error(traceback.format_exc()) | 1966 log.error(traceback.format_exc()) |
1151 raise JSONRPCError( | 1967 raise JSONRPCError( |
1152 'failed to edit permission for user group: `%s` in ' | 1968 'failed to edit permission for user group: `%s` in ' |
1153 'repo: `%s`' % ( | 1969 'repo: `%s`' % ( |
1154 users_group.users_group_name, repo.repo_name | 1970 user_group.users_group_name, repo.repo_name |
1155 ) | 1971 ) |
1156 ) | 1972 ) |
1973 | |
1974 @HasPermissionAllDecorator('hg.admin') | |
1975 def get_repo_group(self, apiuser, repogroupid): | |
1976 """ | |
1977 Returns given repo group together with permissions, and repositories | |
1978 inside the group | |
1979 | |
1980 :param apiuser: filled automatically from apikey | |
1981 :type apiuser: AuthUser | |
1982 :param repogroupid: id/name of repository group | |
1983 :type repogroupid: str or int | |
1984 """ | |
1985 repo_group = get_repo_group_or_error(repogroupid) | |
1986 | |
1987 members = [] | |
1988 for user in repo_group.repo_group_to_perm: | |
1989 perm = user.permission.permission_name | |
1990 user = user.user | |
1991 user_data = { | |
1992 'name': user.username, | |
1993 'type': "user", | |
1994 'permission': perm | |
1995 } | |
1996 members.append(user_data) | |
1997 | |
1998 for user_group in repo_group.users_group_to_perm: | |
1999 perm = user_group.permission.permission_name | |
2000 user_group = user_group.users_group | |
2001 user_group_data = { | |
2002 'name': user_group.users_group_name, | |
2003 'type': "user_group", | |
2004 'permission': perm | |
2005 } | |
2006 members.append(user_group_data) | |
2007 | |
2008 data = repo_group.get_api_data() | |
2009 data["members"] = members | |
2010 return data | |
2011 | |
2012 @HasPermissionAllDecorator('hg.admin') | |
2013 def get_repo_groups(self, apiuser): | |
2014 """ | |
2015 Returns all repository groups | |
2016 | |
2017 :param apiuser: filled automatically from apikey | |
2018 :type apiuser: AuthUser | |
2019 """ | |
2020 result = [] | |
2021 for repo_group in RepoGroupModel().get_all(): | |
2022 result.append(repo_group.get_api_data()) | |
2023 return result | |
2024 | |
2025 @HasPermissionAllDecorator('hg.admin') | |
2026 def create_repo_group(self, apiuser, group_name, description=Optional(''), | |
2027 owner=Optional(OAttr('apiuser')), | |
2028 parent=Optional(None), | |
2029 copy_permissions=Optional(False)): | |
2030 """ | |
2031 Creates a repository group. This command can be executed only using | |
2032 api_key belonging to user with admin rights. | |
2033 | |
2034 :param apiuser: filled automatically from apikey | |
2035 :type apiuser: AuthUser | |
2036 :param group_name: | |
2037 :type group_name: | |
2038 :param description: | |
2039 :type description: | |
2040 :param owner: | |
2041 :type owner: | |
2042 :param parent: | |
2043 :type parent: | |
2044 :param copy_permissions: | |
2045 :type copy_permissions: | |
2046 | |
2047 OUTPUT:: | |
2048 | |
2049 id : <id_given_in_input> | |
2050 result : { | |
2051 "msg": "created new repo group `<repo_group_name>`" | |
2052 "repo_group": <repogroup_object> | |
2053 } | |
2054 error : null | |
2055 | |
2056 ERROR OUTPUT:: | |
2057 | |
2058 id : <id_given_in_input> | |
2059 result : null | |
2060 error : { | |
2061 failed to create repo group `<repogroupid>` | |
2062 } | |
2063 | |
2064 """ | |
2065 if RepoGroup.get_by_group_name(group_name): | |
2066 raise JSONRPCError("repo group `%s` already exist" % (group_name,)) | |
2067 | |
2068 if isinstance(owner, Optional): | |
2069 owner = apiuser.user_id | |
2070 group_description = Optional.extract(description) | |
2071 parent_group = Optional.extract(parent) | |
2072 if not isinstance(parent, Optional): | |
2073 parent_group = get_repo_group_or_error(parent_group) | |
2074 | |
2075 copy_permissions = Optional.extract(copy_permissions) | |
2076 try: | |
2077 repo_group = RepoGroupModel().create( | |
2078 group_name=group_name, | |
2079 group_description=group_description, | |
2080 owner=owner, | |
2081 parent=parent_group, | |
2082 copy_permissions=copy_permissions | |
2083 ) | |
2084 Session().commit() | |
2085 return dict( | |
2086 msg='created new repo group `%s`' % group_name, | |
2087 repo_group=repo_group.get_api_data() | |
2088 ) | |
2089 except Exception: | |
2090 | |
2091 log.error(traceback.format_exc()) | |
2092 raise JSONRPCError('failed to create repo group `%s`' % (group_name,)) | |
2093 | |
2094 @HasPermissionAllDecorator('hg.admin') | |
2095 def update_repo_group(self, apiuser, repogroupid, group_name=Optional(''), | |
2096 description=Optional(''), | |
2097 owner=Optional(OAttr('apiuser')), | |
2098 parent=Optional(None), enable_locking=Optional(False)): | |
2099 repo_group = get_repo_group_or_error(repogroupid) | |
2100 | |
2101 updates = {} | |
2102 try: | |
2103 store_update(updates, group_name, 'group_name') | |
2104 store_update(updates, description, 'group_description') | |
2105 store_update(updates, owner, 'owner') | |
2106 store_update(updates, parent, 'parent_group') | |
2107 store_update(updates, enable_locking, 'enable_locking') | |
2108 repo_group = RepoGroupModel().update(repo_group, updates) | |
2109 Session().commit() | |
2110 return dict( | |
2111 msg='updated repository group ID:%s %s' % (repo_group.group_id, | |
2112 repo_group.group_name), | |
2113 repo_group=repo_group.get_api_data() | |
2114 ) | |
2115 except Exception: | |
2116 log.error(traceback.format_exc()) | |
2117 raise JSONRPCError('failed to update repository group `%s`' | |
2118 % (repogroupid,)) | |
2119 | |
2120 @HasPermissionAllDecorator('hg.admin') | |
2121 def delete_repo_group(self, apiuser, repogroupid): | |
2122 """ | |
2123 | |
2124 :param apiuser: filled automatically from apikey | |
2125 :type apiuser: AuthUser | |
2126 :param repogroupid: name or id of repository group | |
2127 :type repogroupid: str or int | |
2128 | |
2129 OUTPUT:: | |
2130 | |
2131 id : <id_given_in_input> | |
2132 result : { | |
2133 'msg': 'deleted repo group ID:<repogroupid> <repogroupname> | |
2134 'repo_group': null | |
2135 } | |
2136 error : null | |
2137 | |
2138 ERROR OUTPUT:: | |
2139 | |
2140 id : <id_given_in_input> | |
2141 result : null | |
2142 error : { | |
2143 "failed to delete repo group ID:<repogroupid> <repogroupname>" | |
2144 } | |
2145 | |
2146 """ | |
2147 repo_group = get_repo_group_or_error(repogroupid) | |
2148 | |
2149 try: | |
2150 RepoGroupModel().delete(repo_group) | |
2151 Session().commit() | |
2152 return dict( | |
2153 msg='deleted repo group ID:%s %s' % | |
2154 (repo_group.group_id, repo_group.group_name), | |
2155 repo_group=None | |
2156 ) | |
2157 except Exception: | |
2158 log.error(traceback.format_exc()) | |
2159 raise JSONRPCError('failed to delete repo group ID:%s %s' % | |
2160 (repo_group.group_id, repo_group.group_name) | |
2161 ) | |
2162 | |
2163 # permission check inside | |
2164 def grant_user_permission_to_repo_group(self, apiuser, repogroupid, userid, | |
2165 perm, apply_to_children=Optional('none')): | |
2166 """ | |
2167 Grant permission for user on given repository group, or update existing | |
2168 one if found. This command can be executed only using api_key belonging | |
2169 to user with admin rights, or user who has admin right to given repository | |
2170 group. | |
2171 | |
2172 :param apiuser: filled automatically from apikey | |
2173 :type apiuser: AuthUser | |
2174 :param repogroupid: name or id of repository group | |
2175 :type repogroupid: str or int | |
2176 :param userid: | |
2177 :param perm: (group.(none|read|write|admin)) | |
2178 :type perm: str | |
2179 :param apply_to_children: 'none', 'repos', 'groups', 'all' | |
2180 :type apply_to_children: str | |
2181 | |
2182 OUTPUT:: | |
2183 | |
2184 id : <id_given_in_input> | |
2185 result: { | |
2186 "msg" : "Granted perm: `<perm>` (recursive:<apply_to_children>) for user: `<username>` in repo group: `<repo_group_name>`", | |
2187 "success": true | |
2188 } | |
2189 error: null | |
2190 | |
2191 ERROR OUTPUT:: | |
2192 | |
2193 id : <id_given_in_input> | |
2194 result : null | |
2195 error : { | |
2196 "failed to edit permission for user: `<userid>` in repo group: `<repo_group_name>`" | |
2197 } | |
2198 | |
2199 """ | |
2200 | |
2201 repo_group = get_repo_group_or_error(repogroupid) | |
2202 | |
2203 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | |
2204 # check if we have admin permission for this repo group ! | |
2205 if not HasRepoGroupPermissionAnyApi('group.admin')(user=apiuser, | |
2206 group_name=repo_group.group_name): | |
2207 raise JSONRPCError('repository group `%s` does not exist' % (repogroupid,)) | |
2208 | |
2209 user = get_user_or_error(userid) | |
2210 perm = get_perm_or_error(perm, prefix='group.') | |
2211 apply_to_children = Optional.extract(apply_to_children) | |
2212 | |
2213 try: | |
2214 RepoGroupModel().add_permission(repo_group=repo_group, | |
2215 obj=user, | |
2216 obj_type="user", | |
2217 perm=perm, | |
2218 recursive=apply_to_children) | |
2219 Session().commit() | |
2220 return dict( | |
2221 msg='Granted perm: `%s` (recursive:%s) for user: `%s` in repo group: `%s`' % ( | |
2222 perm.permission_name, apply_to_children, user.username, repo_group.name | |
2223 ), | |
2224 success=True | |
2225 ) | |
2226 except Exception: | |
2227 log.error(traceback.format_exc()) | |
2228 raise JSONRPCError( | |
2229 'failed to edit permission for user: `%s` in repo group: `%s`' % ( | |
2230 userid, repo_group.name)) | |
2231 | |
2232 # permission check inside | |
2233 def revoke_user_permission_from_repo_group(self, apiuser, repogroupid, userid, | |
2234 apply_to_children=Optional('none')): | |
2235 """ | |
2236 Revoke permission for user on given repository group. This command can | |
2237 be executed only using api_key belonging to user with admin rights, or | |
2238 user who has admin right to given repository group. | |
2239 | |
2240 :param apiuser: filled automatically from apikey | |
2241 :type apiuser: AuthUser | |
2242 :param repogroupid: name or id of repository group | |
2243 :type repogroupid: str or int | |
2244 :param userid: | |
2245 :type userid: | |
2246 :param apply_to_children: 'none', 'repos', 'groups', 'all' | |
2247 :type apply_to_children: str | |
2248 | |
2249 OUTPUT:: | |
2250 | |
2251 id : <id_given_in_input> | |
2252 result: { | |
2253 "msg" : "Revoked perm (recursive:<apply_to_children>) for user: `<username>` in repo group: `<repo_group_name>`", | |
2254 "success": true | |
2255 } | |
2256 error: null | |
2257 | |
2258 ERROR OUTPUT:: | |
2259 | |
2260 id : <id_given_in_input> | |
2261 result : null | |
2262 error : { | |
2263 "failed to edit permission for user: `<userid>` in repo group: `<repo_group_name>`" | |
2264 } | |
2265 | |
2266 """ | |
2267 | |
2268 repo_group = get_repo_group_or_error(repogroupid) | |
2269 | |
2270 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | |
2271 # check if we have admin permission for this repo group ! | |
2272 if not HasRepoGroupPermissionAnyApi('group.admin')(user=apiuser, | |
2273 group_name=repo_group.group_name): | |
2274 raise JSONRPCError('repository group `%s` does not exist' % (repogroupid,)) | |
2275 | |
2276 user = get_user_or_error(userid) | |
2277 apply_to_children = Optional.extract(apply_to_children) | |
2278 | |
2279 try: | |
2280 RepoGroupModel().delete_permission(repo_group=repo_group, | |
2281 obj=user, | |
2282 obj_type="user", | |
2283 recursive=apply_to_children) | |
2284 | |
2285 Session().commit() | |
2286 return dict( | |
2287 msg='Revoked perm (recursive:%s) for user: `%s` in repo group: `%s`' % ( | |
2288 apply_to_children, user.username, repo_group.name | |
2289 ), | |
2290 success=True | |
2291 ) | |
2292 except Exception: | |
2293 log.error(traceback.format_exc()) | |
2294 raise JSONRPCError( | |
2295 'failed to edit permission for user: `%s` in repo group: `%s`' % ( | |
2296 userid, repo_group.name)) | |
2297 | |
2298 # permission check inside | |
2299 def grant_user_group_permission_to_repo_group( | |
2300 self, apiuser, repogroupid, usergroupid, perm, | |
2301 apply_to_children=Optional('none'),): | |
2302 """ | |
2303 Grant permission for user group on given repository group, or update | |
2304 existing one if found. This command can be executed only using | |
2305 api_key belonging to user with admin rights, or user who has admin | |
2306 right to given repository group. | |
2307 | |
2308 :param apiuser: filled automatically from apikey | |
2309 :type apiuser: AuthUser | |
2310 :param repogroupid: name or id of repository group | |
2311 :type repogroupid: str or int | |
2312 :param usergroupid: id of usergroup | |
2313 :type usergroupid: str or int | |
2314 :param perm: (group.(none|read|write|admin)) | |
2315 :type perm: str | |
2316 :param apply_to_children: 'none', 'repos', 'groups', 'all' | |
2317 :type apply_to_children: str | |
2318 | |
2319 OUTPUT:: | |
2320 | |
2321 id : <id_given_in_input> | |
2322 result : { | |
2323 "msg" : "Granted perm: `<perm>` (recursive:<apply_to_children>) for user group: `<usersgroupname>` in repo group: `<repo_group_name>`", | |
2324 "success": true | |
2325 | |
2326 } | |
2327 error : null | |
2328 | |
2329 ERROR OUTPUT:: | |
2330 | |
2331 id : <id_given_in_input> | |
2332 result : null | |
2333 error : { | |
2334 "failed to edit permission for user group: `<usergroup>` in repo group: `<repo_group_name>`" | |
2335 } | |
2336 | |
2337 """ | |
2338 repo_group = get_repo_group_or_error(repogroupid) | |
2339 perm = get_perm_or_error(perm, prefix='group.') | |
2340 user_group = get_user_group_or_error(usergroupid) | |
2341 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | |
2342 # check if we have admin permission for this repo group ! | |
2343 _perms = ('group.admin',) | |
2344 if not HasRepoGroupPermissionAnyApi(*_perms)( | |
2345 user=apiuser, group_name=repo_group.group_name): | |
2346 raise JSONRPCError( | |
2347 'repository group `%s` does not exist' % (repogroupid,)) | |
2348 | |
2349 # check if we have at least read permission for this user group ! | |
2350 _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',) | |
2351 if not HasUserGroupPermissionAny(*_perms)( | |
2352 user=apiuser, user_group_name=user_group.users_group_name): | |
2353 raise JSONRPCError( | |
2354 'user group `%s` does not exist' % (usergroupid,)) | |
2355 | |
2356 apply_to_children = Optional.extract(apply_to_children) | |
2357 | |
2358 try: | |
2359 RepoGroupModel().add_permission(repo_group=repo_group, | |
2360 obj=user_group, | |
2361 obj_type="user_group", | |
2362 perm=perm, | |
2363 recursive=apply_to_children) | |
2364 Session().commit() | |
2365 return dict( | |
2366 msg='Granted perm: `%s` (recursive:%s) for user group: `%s` in repo group: `%s`' % ( | |
2367 perm.permission_name, apply_to_children, | |
2368 user_group.users_group_name, repo_group.name | |
2369 ), | |
2370 success=True | |
2371 ) | |
2372 except Exception: | |
2373 log.error(traceback.format_exc()) | |
2374 raise JSONRPCError( | |
2375 'failed to edit permission for user group: `%s` in ' | |
2376 'repo group: `%s`' % ( | |
2377 usergroupid, repo_group.name | |
2378 ) | |
2379 ) | |
2380 | |
2381 # permission check inside | |
2382 def revoke_user_group_permission_from_repo_group( | |
2383 self, apiuser, repogroupid, usergroupid, | |
2384 apply_to_children=Optional('none')): | |
2385 """ | |
2386 Revoke permission for user group on given repository. This command can be | |
2387 executed only using api_key belonging to user with admin rights, or | |
2388 user who has admin right to given repository group. | |
2389 | |
2390 :param apiuser: filled automatically from apikey | |
2391 :type apiuser: AuthUser | |
2392 :param repogroupid: name or id of repository group | |
2393 :type repogroupid: str or int | |
2394 :param usergroupid: | |
2395 :param apply_to_children: 'none', 'repos', 'groups', 'all' | |
2396 :type apply_to_children: str | |
2397 | |
2398 OUTPUT:: | |
2399 | |
2400 id : <id_given_in_input> | |
2401 result: { | |
2402 "msg" : "Revoked perm (recursive:<apply_to_children>) for user group: `<usersgroupname>` in repo group: `<repo_group_name>`", | |
2403 "success": true | |
2404 } | |
2405 error: null | |
2406 | |
2407 ERROR OUTPUT:: | |
2408 | |
2409 id : <id_given_in_input> | |
2410 result : null | |
2411 error : { | |
2412 "failed to edit permission for user group: `<usergroup>` in repo group: `<repo_group_name>`" | |
2413 } | |
2414 | |
2415 | |
2416 """ | |
2417 repo_group = get_repo_group_or_error(repogroupid) | |
2418 user_group = get_user_group_or_error(usergroupid) | |
2419 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | |
2420 # check if we have admin permission for this repo group ! | |
2421 _perms = ('group.admin',) | |
2422 if not HasRepoGroupPermissionAnyApi(*_perms)( | |
2423 user=apiuser, group_name=repo_group.group_name): | |
2424 raise JSONRPCError( | |
2425 'repository group `%s` does not exist' % (repogroupid,)) | |
2426 | |
2427 # check if we have at least read permission for this user group ! | |
2428 _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',) | |
2429 if not HasUserGroupPermissionAny(*_perms)( | |
2430 user=apiuser, user_group_name=user_group.users_group_name): | |
2431 raise JSONRPCError( | |
2432 'user group `%s` does not exist' % (usergroupid,)) | |
2433 | |
2434 apply_to_children = Optional.extract(apply_to_children) | |
2435 | |
2436 try: | |
2437 RepoGroupModel().delete_permission(repo_group=repo_group, | |
2438 obj=user_group, | |
2439 obj_type="user_group", | |
2440 recursive=apply_to_children) | |
2441 Session().commit() | |
2442 return dict( | |
2443 msg='Revoked perm (recursive:%s) for user group: `%s` in repo group: `%s`' % ( | |
2444 apply_to_children, user_group.users_group_name, repo_group.name | |
2445 ), | |
2446 success=True | |
2447 ) | |
2448 except Exception: | |
2449 log.error(traceback.format_exc()) | |
2450 raise JSONRPCError( | |
2451 'failed to edit permission for user group: `%s` in repo group: `%s`' % ( | |
2452 user_group.users_group_name, repo_group.name | |
2453 ) | |
2454 ) | |
2455 | |
2456 def get_gist(self, apiuser, gistid): | |
2457 """ | |
2458 Get given gist by id | |
2459 | |
2460 :param apiuser: filled automatically from apikey | |
2461 :type apiuser: AuthUser | |
2462 :param gistid: id of private or public gist | |
2463 :type gistid: str | |
2464 """ | |
2465 gist = get_gist_or_error(gistid) | |
2466 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | |
2467 if gist.gist_owner != apiuser.user_id: | |
2468 raise JSONRPCError('gist `%s` does not exist' % (gistid,)) | |
2469 return gist.get_api_data() | |
2470 | |
2471 def get_gists(self, apiuser, userid=Optional(OAttr('apiuser'))): | |
2472 """ | |
2473 Get all gists for given user. If userid is empty returned gists | |
2474 are for user who called the api | |
2475 | |
2476 :param apiuser: filled automatically from apikey | |
2477 :type apiuser: AuthUser | |
2478 :param userid: user to get gists for | |
2479 :type userid: Optional(str or int) | |
2480 """ | |
2481 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | |
2482 # make sure normal user does not pass someone else userid, | |
2483 # he is not allowed to do that | |
2484 if not isinstance(userid, Optional) and userid != apiuser.user_id: | |
2485 raise JSONRPCError( | |
2486 'userid is not the same as your user' | |
2487 ) | |
2488 | |
2489 if isinstance(userid, Optional): | |
2490 user_id = apiuser.user_id | |
2491 else: | |
2492 user_id = get_user_or_error(userid).user_id | |
2493 | |
2494 gists = [] | |
2495 _gists = Gist().query()\ | |
2496 .filter(or_(Gist.gist_expires == -1, Gist.gist_expires >= time.time()))\ | |
2497 .filter(Gist.gist_owner == user_id)\ | |
2498 .order_by(Gist.created_on.desc()) | |
2499 for gist in _gists: | |
2500 gists.append(gist.get_api_data()) | |
2501 return gists | |
1157 | 2502 |
1158 def create_gist(self, apiuser, files, owner=Optional(OAttr('apiuser')), | 2503 def create_gist(self, apiuser, files, owner=Optional(OAttr('apiuser')), |
1159 gist_type=Optional(Gist.GIST_PUBLIC), lifetime=Optional(-1), | 2504 gist_type=Optional(Gist.GIST_PUBLIC), lifetime=Optional(-1), |
1160 description=Optional('')): | 2505 description=Optional('')): |
1161 | 2506 |
2507 """ | |
2508 Creates new Gist | |
2509 | |
2510 :param apiuser: filled automatically from apikey | |
2511 :type apiuser: AuthUser | |
2512 :param files: files to be added to gist | |
2513 {'filename': {'content':'...', 'lexer': null}, | |
2514 'filename2': {'content':'...', 'lexer': null}} | |
2515 :type files: dict | |
2516 :param owner: gist owner, defaults to api method caller | |
2517 :type owner: Optional(str or int) | |
2518 :param gist_type: type of gist 'public' or 'private' | |
2519 :type gist_type: Optional(str) | |
2520 :param lifetime: time in minutes of gist lifetime | |
2521 :type lifetime: Optional(int) | |
2522 :param description: gist description | |
2523 :type description: Optional(str) | |
2524 | |
2525 OUTPUT:: | |
2526 | |
2527 id : <id_given_in_input> | |
2528 result : { | |
2529 "msg": "created new gist", | |
2530 "gist": {} | |
2531 } | |
2532 error : null | |
2533 | |
2534 ERROR OUTPUT:: | |
2535 | |
2536 id : <id_given_in_input> | |
2537 result : null | |
2538 error : { | |
2539 "failed to create gist" | |
2540 } | |
2541 | |
2542 """ | |
1162 try: | 2543 try: |
1163 if isinstance(owner, Optional): | 2544 if isinstance(owner, Optional): |
1164 owner = apiuser.user_id | 2545 owner = apiuser.user_id |
1165 | 2546 |
1166 owner = get_user_or_error(owner) | 2547 owner = get_user_or_error(owner) |
1167 description = Optional.extract(description) | 2548 description = Optional.extract(description) |
1168 gist_type = Optional.extract(gist_type) | 2549 gist_type = Optional.extract(gist_type) |
1169 lifetime = Optional.extract(lifetime) | 2550 lifetime = Optional.extract(lifetime) |
1170 | 2551 |
1171 # files: { | |
1172 # 'filename': {'content':'...', 'lexer': null}, | |
1173 # 'filename2': {'content':'...', 'lexer': null} | |
1174 #} | |
1175 gist = GistModel().create(description=description, | 2552 gist = GistModel().create(description=description, |
1176 owner=owner, | 2553 owner=owner, |
1177 gist_mapping=files, | 2554 gist_mapping=files, |
1178 gist_type=gist_type, | 2555 gist_type=gist_type, |
1179 lifetime=lifetime) | 2556 lifetime=lifetime) |
1183 gist=gist.get_api_data() | 2560 gist=gist.get_api_data() |
1184 ) | 2561 ) |
1185 except Exception: | 2562 except Exception: |
1186 log.error(traceback.format_exc()) | 2563 log.error(traceback.format_exc()) |
1187 raise JSONRPCError('failed to create gist') | 2564 raise JSONRPCError('failed to create gist') |
2565 | |
2566 # def update_gist(self, apiuser, gistid, files, owner=Optional(OAttr('apiuser')), | |
2567 # gist_type=Optional(Gist.GIST_PUBLIC), | |
2568 # gist_lifetime=Optional(-1), gist_description=Optional('')): | |
2569 # gist = get_gist_or_error(gistid) | |
2570 # updates = {} | |
2571 | |
2572 # permission check inside | |
2573 def delete_gist(self, apiuser, gistid): | |
2574 """ | |
2575 Deletes existing gist | |
2576 | |
2577 :param apiuser: filled automatically from apikey | |
2578 :type apiuser: AuthUser | |
2579 :param gistid: id of gist to delete | |
2580 :type gistid: str | |
2581 | |
2582 OUTPUT:: | |
2583 | |
2584 id : <id_given_in_input> | |
2585 result : { | |
2586 "deleted gist ID: <gist_id>", | |
2587 "gist": null | |
2588 } | |
2589 error : null | |
2590 | |
2591 ERROR OUTPUT:: | |
2592 | |
2593 id : <id_given_in_input> | |
2594 result : null | |
2595 error : { | |
2596 "failed to delete gist ID:<gist_id>" | |
2597 } | |
2598 | |
2599 """ | |
2600 gist = get_gist_or_error(gistid) | |
2601 if not HasPermissionAnyApi('hg.admin')(user=apiuser): | |
2602 if gist.gist_owner != apiuser.user_id: | |
2603 raise JSONRPCError('gist `%s` does not exist' % (gistid,)) | |
2604 | |
2605 try: | |
2606 GistModel().delete(gist) | |
2607 Session().commit() | |
2608 return dict( | |
2609 msg='deleted gist ID:%s' % (gist.gist_access_id,), | |
2610 gist=None | |
2611 ) | |
2612 except Exception: | |
2613 log.error(traceback.format_exc()) | |
2614 raise JSONRPCError('failed to delete gist ID:%s' | |
2615 % (gist.gist_access_id,)) |