##// END OF EJS Templates
api: expose more details of auth tokens in get_user api call.
marcink -
r1522:82f2feee default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,471 +1,472 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2011-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22
23 23 from rhodecode.api import jsonrpc_method, JSONRPCError, JSONRPCForbidden
24 24 from rhodecode.api.utils import (
25 25 Optional, OAttr, has_superadmin_permission, get_user_or_error, store_update)
26 26 from rhodecode.lib.auth import AuthUser, PasswordGenerator
27 27 from rhodecode.lib.exceptions import DefaultUserException
28 28 from rhodecode.lib.utils2 import safe_int, str2bool
29 29 from rhodecode.model.db import Session, User, Repository
30 30 from rhodecode.model.user import UserModel
31 31
32 32
33 33 log = logging.getLogger(__name__)
34 34
35 35
36 36 @jsonrpc_method()
37 37 def get_user(request, apiuser, userid=Optional(OAttr('apiuser'))):
38 38 """
39 39 Returns the information associated with a username or userid.
40 40
41 41 * If the ``userid`` is not set, this command returns the information
42 42 for the ``userid`` calling the method.
43 43
44 44 .. note::
45 45
46 46 Normal users may only run this command against their ``userid``. For
47 47 full privileges you must run this command using an |authtoken| with
48 48 admin rights.
49 49
50 50 :param apiuser: This is filled automatically from the |authtoken|.
51 51 :type apiuser: AuthUser
52 52 :param userid: Sets the userid for which data will be returned.
53 53 :type userid: Optional(str or int)
54 54
55 55 Example output:
56 56
57 57 .. code-block:: bash
58 58
59 59 {
60 60 "error": null,
61 61 "id": <id>,
62 62 "result": {
63 63 "active": true,
64 64 "admin": false,
65 65 "api_keys": [ list of keys ],
66 "auth_tokens": [ list of tokens with details ],
66 67 "email": "user@example.com",
67 68 "emails": [
68 69 "user@example.com"
69 70 ],
70 71 "extern_name": "rhodecode",
71 72 "extern_type": "rhodecode",
72 73 "firstname": "username",
73 74 "ip_addresses": [],
74 75 "language": null,
75 76 "last_login": "Timestamp",
76 77 "lastname": "surnae",
77 78 "permissions": {
78 79 "global": [
79 80 "hg.inherit_default_perms.true",
80 81 "usergroup.read",
81 82 "hg.repogroup.create.false",
82 83 "hg.create.none",
83 84 "hg.password_reset.enabled",
84 85 "hg.extern_activate.manual",
85 86 "hg.create.write_on_repogroup.false",
86 87 "hg.usergroup.create.false",
87 88 "group.none",
88 89 "repository.none",
89 90 "hg.register.none",
90 91 "hg.fork.repository"
91 92 ],
92 93 "repositories": { "username/example": "repository.write"},
93 94 "repositories_groups": { "user-group/repo": "group.none" },
94 95 "user_groups": { "user_group_name": "usergroup.read" }
95 96 },
96 97 "user_id": 32,
97 98 "username": "username"
98 99 }
99 100 }
100 101 """
101 102
102 103 if not has_superadmin_permission(apiuser):
103 104 # make sure normal user does not pass someone else userid,
104 105 # he is not allowed to do that
105 106 if not isinstance(userid, Optional) and userid != apiuser.user_id:
106 107 raise JSONRPCError('userid is not the same as your user')
107 108
108 109 userid = Optional.extract(userid, evaluate_locals=locals())
109 110 userid = getattr(userid, 'user_id', userid)
110 111
111 112 user = get_user_or_error(userid)
112 113 data = user.get_api_data(include_secrets=True)
113 114 data['permissions'] = AuthUser(user_id=user.user_id).permissions
114 115 return data
115 116
116 117
117 118 @jsonrpc_method()
118 119 def get_users(request, apiuser):
119 120 """
120 121 Lists all users in the |RCE| user database.
121 122
122 123 This command can only be run using an |authtoken| with admin rights to
123 124 the specified repository.
124 125
125 126 This command takes the following options:
126 127
127 128 :param apiuser: This is filled automatically from the |authtoken|.
128 129 :type apiuser: AuthUser
129 130
130 131 Example output:
131 132
132 133 .. code-block:: bash
133 134
134 135 id : <id_given_in_input>
135 136 result: [<user_object>, ...]
136 137 error: null
137 138 """
138 139
139 140 if not has_superadmin_permission(apiuser):
140 141 raise JSONRPCForbidden()
141 142
142 143 result = []
143 144 users_list = User.query().order_by(User.username) \
144 145 .filter(User.username != User.DEFAULT_USER) \
145 146 .all()
146 147 for user in users_list:
147 148 result.append(user.get_api_data(include_secrets=True))
148 149 return result
149 150
150 151
151 152 @jsonrpc_method()
152 153 def create_user(request, apiuser, username, email, password=Optional(''),
153 154 firstname=Optional(''), lastname=Optional(''),
154 155 active=Optional(True), admin=Optional(False),
155 156 extern_name=Optional('rhodecode'),
156 157 extern_type=Optional('rhodecode'),
157 158 force_password_change=Optional(False),
158 159 create_personal_repo_group=Optional(None)):
159 160 """
160 161 Creates a new user and returns the new user object.
161 162
162 163 This command can only be run using an |authtoken| with admin rights to
163 164 the specified repository.
164 165
165 166 This command takes the following options:
166 167
167 168 :param apiuser: This is filled automatically from the |authtoken|.
168 169 :type apiuser: AuthUser
169 170 :param username: Set the new username.
170 171 :type username: str or int
171 172 :param email: Set the user email address.
172 173 :type email: str
173 174 :param password: Set the new user password.
174 175 :type password: Optional(str)
175 176 :param firstname: Set the new user firstname.
176 177 :type firstname: Optional(str)
177 178 :param lastname: Set the new user surname.
178 179 :type lastname: Optional(str)
179 180 :param active: Set the user as active.
180 181 :type active: Optional(``True`` | ``False``)
181 182 :param admin: Give the new user admin rights.
182 183 :type admin: Optional(``True`` | ``False``)
183 184 :param extern_name: Set the authentication plugin name.
184 185 Using LDAP this is filled with LDAP UID.
185 186 :type extern_name: Optional(str)
186 187 :param extern_type: Set the new user authentication plugin.
187 188 :type extern_type: Optional(str)
188 189 :param force_password_change: Force the new user to change password
189 190 on next login.
190 191 :type force_password_change: Optional(``True`` | ``False``)
191 192 :param create_personal_repo_group: Create personal repo group for this user
192 193 :type create_personal_repo_group: Optional(``True`` | ``False``)
193 194 Example output:
194 195
195 196 .. code-block:: bash
196 197
197 198 id : <id_given_in_input>
198 199 result: {
199 200 "msg" : "created new user `<username>`",
200 201 "user": <user_obj>
201 202 }
202 203 error: null
203 204
204 205 Example error output:
205 206
206 207 .. code-block:: bash
207 208
208 209 id : <id_given_in_input>
209 210 result : null
210 211 error : {
211 212 "user `<username>` already exist"
212 213 or
213 214 "email `<email>` already exist"
214 215 or
215 216 "failed to create user `<username>`"
216 217 }
217 218
218 219 """
219 220 if not has_superadmin_permission(apiuser):
220 221 raise JSONRPCForbidden()
221 222
222 223 if UserModel().get_by_username(username):
223 224 raise JSONRPCError("user `%s` already exist" % (username,))
224 225
225 226 if UserModel().get_by_email(email, case_insensitive=True):
226 227 raise JSONRPCError("email `%s` already exist" % (email,))
227 228
228 229 # generate random password if we actually given the
229 230 # extern_name and it's not rhodecode
230 231 if (not isinstance(extern_name, Optional) and
231 232 Optional.extract(extern_name) != 'rhodecode'):
232 233 # generate temporary password if user is external
233 234 password = PasswordGenerator().gen_password(length=16)
234 235 create_repo_group = Optional.extract(create_personal_repo_group)
235 236 if isinstance(create_repo_group, basestring):
236 237 create_repo_group = str2bool(create_repo_group)
237 238
238 239 try:
239 240 user = UserModel().create_or_update(
240 241 username=Optional.extract(username),
241 242 password=Optional.extract(password),
242 243 email=Optional.extract(email),
243 244 firstname=Optional.extract(firstname),
244 245 lastname=Optional.extract(lastname),
245 246 active=Optional.extract(active),
246 247 admin=Optional.extract(admin),
247 248 extern_type=Optional.extract(extern_type),
248 249 extern_name=Optional.extract(extern_name),
249 250 force_password_change=Optional.extract(force_password_change),
250 251 create_repo_group=create_repo_group
251 252 )
252 253 Session().commit()
253 254 return {
254 255 'msg': 'created new user `%s`' % username,
255 256 'user': user.get_api_data(include_secrets=True)
256 257 }
257 258 except Exception:
258 259 log.exception('Error occurred during creation of user')
259 260 raise JSONRPCError('failed to create user `%s`' % (username,))
260 261
261 262
262 263 @jsonrpc_method()
263 264 def update_user(request, apiuser, userid, username=Optional(None),
264 265 email=Optional(None), password=Optional(None),
265 266 firstname=Optional(None), lastname=Optional(None),
266 267 active=Optional(None), admin=Optional(None),
267 268 extern_type=Optional(None), extern_name=Optional(None), ):
268 269 """
269 270 Updates the details for the specified user, if that user exists.
270 271
271 272 This command can only be run using an |authtoken| with admin rights to
272 273 the specified repository.
273 274
274 275 This command takes the following options:
275 276
276 277 :param apiuser: This is filled automatically from |authtoken|.
277 278 :type apiuser: AuthUser
278 279 :param userid: Set the ``userid`` to update.
279 280 :type userid: str or int
280 281 :param username: Set the new username.
281 282 :type username: str or int
282 283 :param email: Set the new email.
283 284 :type email: str
284 285 :param password: Set the new password.
285 286 :type password: Optional(str)
286 287 :param firstname: Set the new first name.
287 288 :type firstname: Optional(str)
288 289 :param lastname: Set the new surname.
289 290 :type lastname: Optional(str)
290 291 :param active: Set the new user as active.
291 292 :type active: Optional(``True`` | ``False``)
292 293 :param admin: Give the user admin rights.
293 294 :type admin: Optional(``True`` | ``False``)
294 295 :param extern_name: Set the authentication plugin user name.
295 296 Using LDAP this is filled with LDAP UID.
296 297 :type extern_name: Optional(str)
297 298 :param extern_type: Set the authentication plugin type.
298 299 :type extern_type: Optional(str)
299 300
300 301
301 302 Example output:
302 303
303 304 .. code-block:: bash
304 305
305 306 id : <id_given_in_input>
306 307 result: {
307 308 "msg" : "updated user ID:<userid> <username>",
308 309 "user": <user_object>,
309 310 }
310 311 error: null
311 312
312 313 Example error output:
313 314
314 315 .. code-block:: bash
315 316
316 317 id : <id_given_in_input>
317 318 result : null
318 319 error : {
319 320 "failed to update user `<username>`"
320 321 }
321 322
322 323 """
323 324 if not has_superadmin_permission(apiuser):
324 325 raise JSONRPCForbidden()
325 326
326 327 user = get_user_or_error(userid)
327 328
328 329 # only non optional arguments will be stored in updates
329 330 updates = {}
330 331
331 332 try:
332 333
333 334 store_update(updates, username, 'username')
334 335 store_update(updates, password, 'password')
335 336 store_update(updates, email, 'email')
336 337 store_update(updates, firstname, 'name')
337 338 store_update(updates, lastname, 'lastname')
338 339 store_update(updates, active, 'active')
339 340 store_update(updates, admin, 'admin')
340 341 store_update(updates, extern_name, 'extern_name')
341 342 store_update(updates, extern_type, 'extern_type')
342 343
343 344 user = UserModel().update_user(user, **updates)
344 345 Session().commit()
345 346 return {
346 347 'msg': 'updated user ID:%s %s' % (user.user_id, user.username),
347 348 'user': user.get_api_data(include_secrets=True)
348 349 }
349 350 except DefaultUserException:
350 351 log.exception("Default user edit exception")
351 352 raise JSONRPCError('editing default user is forbidden')
352 353 except Exception:
353 354 log.exception("Error occurred during update of user")
354 355 raise JSONRPCError('failed to update user `%s`' % (userid,))
355 356
356 357
357 358 @jsonrpc_method()
358 359 def delete_user(request, apiuser, userid):
359 360 """
360 361 Deletes the specified user from the |RCE| user database.
361 362
362 363 This command can only be run using an |authtoken| with admin rights to
363 364 the specified repository.
364 365
365 366 .. important::
366 367
367 368 Ensure all open pull requests and open code review
368 369 requests to this user are close.
369 370
370 371 Also ensure all repositories, or repository groups owned by this
371 372 user are reassigned before deletion.
372 373
373 374 This command takes the following options:
374 375
375 376 :param apiuser: This is filled automatically from the |authtoken|.
376 377 :type apiuser: AuthUser
377 378 :param userid: Set the user to delete.
378 379 :type userid: str or int
379 380
380 381 Example output:
381 382
382 383 .. code-block:: bash
383 384
384 385 id : <id_given_in_input>
385 386 result: {
386 387 "msg" : "deleted user ID:<userid> <username>",
387 388 "user": null
388 389 }
389 390 error: null
390 391
391 392 Example error output:
392 393
393 394 .. code-block:: bash
394 395
395 396 id : <id_given_in_input>
396 397 result : null
397 398 error : {
398 399 "failed to delete user ID:<userid> <username>"
399 400 }
400 401
401 402 """
402 403 if not has_superadmin_permission(apiuser):
403 404 raise JSONRPCForbidden()
404 405
405 406 user = get_user_or_error(userid)
406 407
407 408 try:
408 409 UserModel().delete(userid)
409 410 Session().commit()
410 411 return {
411 412 'msg': 'deleted user ID:%s %s' % (user.user_id, user.username),
412 413 'user': None
413 414 }
414 415 except Exception:
415 416 log.exception("Error occurred during deleting of user")
416 417 raise JSONRPCError(
417 418 'failed to delete user ID:%s %s' % (user.user_id, user.username))
418 419
419 420
420 421 @jsonrpc_method()
421 422 def get_user_locks(request, apiuser, userid=Optional(OAttr('apiuser'))):
422 423 """
423 424 Displays all repositories locked by the specified user.
424 425
425 426 * If this command is run by a non-admin user, it returns
426 427 a list of |repos| locked by that user.
427 428
428 429 This command takes the following options:
429 430
430 431 :param apiuser: This is filled automatically from the |authtoken|.
431 432 :type apiuser: AuthUser
432 433 :param userid: Sets the userid whose list of locked |repos| will be
433 434 displayed.
434 435 :type userid: Optional(str or int)
435 436
436 437 Example output:
437 438
438 439 .. code-block:: bash
439 440
440 441 id : <id_given_in_input>
441 442 result : {
442 443 [repo_object, repo_object,...]
443 444 }
444 445 error : null
445 446 """
446 447
447 448 include_secrets = False
448 449 if not has_superadmin_permission(apiuser):
449 450 # make sure normal user does not pass someone else userid,
450 451 # he is not allowed to do that
451 452 if not isinstance(userid, Optional) and userid != apiuser.user_id:
452 453 raise JSONRPCError('userid is not the same as your user')
453 454 else:
454 455 include_secrets = True
455 456
456 457 userid = Optional.extract(userid, evaluate_locals=locals())
457 458 userid = getattr(userid, 'user_id', userid)
458 459 user = get_user_or_error(userid)
459 460
460 461 ret = []
461 462
462 463 # show all locks
463 464 for r in Repository.getAll():
464 465 _user_id, _time, _reason = r.locked
465 466 if _user_id and _time:
466 467 _api_data = r.get_api_data(include_secrets=include_secrets)
467 468 # if we use user filter just show the locks for this user
468 469 if safe_int(_user_id) == user.user_id:
469 470 ret.append(_api_data)
470 471
471 472 return ret
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now