##// END OF EJS Templates
API get_user and get_repo methods can fetch by id or names
marcink -
r2010:14dffcfe beta
parent child Browse files
Show More
@@ -1,627 +1,627 b''
1 .. _api:
1 .. _api:
2
2
3
3
4 API
4 API
5 ===
5 ===
6
6
7
7
8 Starting from RhodeCode version 1.2 a simple API was implemented.
8 Starting from RhodeCode version 1.2 a simple API was implemented.
9 There's a single schema for calling all api methods. API is implemented
9 There's a single schema for calling all api methods. API is implemented
10 with JSON protocol both ways. An url to send API request in RhodeCode is
10 with JSON protocol both ways. An url to send API request in RhodeCode is
11 <your_server>/_admin/api
11 <your_server>/_admin/api
12
12
13 API ACCESS FOR WEB VIEWS
13 API ACCESS FOR WEB VIEWS
14 ++++++++++++++++++++++++
14 ++++++++++++++++++++++++
15
15
16 API access can also be turned on for each web view in RhodeCode that is
16 API access can also be turned on for each web view in RhodeCode that is
17 decorated with `@LoginRequired` decorator. To enable API access simple change
17 decorated with `@LoginRequired` decorator. To enable API access simple change
18 the standard login decorator to `@LoginRequired(api_access=True)`.
18 the standard login decorator to `@LoginRequired(api_access=True)`.
19 After this change, a rhodecode view can be accessed without login by adding a
19 After this change, a rhodecode view can be accessed without login by adding a
20 GET parameter `?api_key=<api_key>` to url. By default this is only
20 GET parameter `?api_key=<api_key>` to url. By default this is only
21 enabled on RSS/ATOM feed views.
21 enabled on RSS/ATOM feed views.
22
22
23
23
24 API ACCESS
24 API ACCESS
25 ++++++++++
25 ++++++++++
26
26
27 All clients are required to send JSON-RPC spec JSON data::
27 All clients are required to send JSON-RPC spec JSON data::
28
28
29 {
29 {
30 "id:<id>,
30 "id:<id>,
31 "api_key":"<api_key>",
31 "api_key":"<api_key>",
32 "method":"<method_name>",
32 "method":"<method_name>",
33 "args":{"<arg_key>":"<arg_val>"}
33 "args":{"<arg_key>":"<arg_val>"}
34 }
34 }
35
35
36 Example call for autopulling remotes repos using curl::
36 Example call for autopulling remotes repos using curl::
37 curl https://server.com/_admin/api -X POST -H 'content-type:text/plain' --data-binary '{"id":1,"api_key":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull","args":{"repo":"CPython"}}'
37 curl https://server.com/_admin/api -X POST -H 'content-type:text/plain' --data-binary '{"id":1,"api_key":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull","args":{"repo":"CPython"}}'
38
38
39 Simply provide
39 Simply provide
40 - *id* A value of any type, which is used to match the response with the request that it is replying to.
40 - *id* A value of any type, which is used to match the response with the request that it is replying to.
41 - *api_key* for access and permission validation.
41 - *api_key* for access and permission validation.
42 - *method* is name of method to call
42 - *method* is name of method to call
43 - *args* is an key:value list of arguments to pass to method
43 - *args* is an key:value list of arguments to pass to method
44
44
45 .. note::
45 .. note::
46
46
47 api_key can be found in your user account page
47 api_key can be found in your user account page
48
48
49
49
50 RhodeCode API will return always a JSON-RPC response::
50 RhodeCode API will return always a JSON-RPC response::
51
51
52 {
52 {
53 "id":<id>,
53 "id":<id>,
54 "result": "<result>",
54 "result": "<result>",
55 "error": null
55 "error": null
56 }
56 }
57
57
58 All responses from API will be `HTTP/1.0 200 OK`, if there's an error while
58 All responses from API will be `HTTP/1.0 200 OK`, if there's an error while
59 calling api *error* key from response will contain failure description
59 calling api *error* key from response will contain failure description
60 and result will be null.
60 and result will be null.
61
61
62 API METHODS
62 API METHODS
63 +++++++++++
63 +++++++++++
64
64
65
65
66 pull
66 pull
67 ----
67 ----
68
68
69 Pulls given repo from remote location. Can be used to automatically keep
69 Pulls given repo from remote location. Can be used to automatically keep
70 remote repos up to date. This command can be executed only using api_key
70 remote repos up to date. This command can be executed only using api_key
71 belonging to user with admin rights
71 belonging to user with admin rights
72
72
73 INPUT::
73 INPUT::
74
74
75 api_key : "<api_key>"
75 api_key : "<api_key>"
76 method : "pull"
76 method : "pull"
77 args : {
77 args : {
78 "repo_name" : "<reponame>"
78 "repo_name" : "<reponame>"
79 }
79 }
80
80
81 OUTPUT::
81 OUTPUT::
82
82
83 result : "Pulled from <reponame>"
83 result : "Pulled from <reponame>"
84 error : null
84 error : null
85
85
86
86
87 get_user
87 get_user
88 --------
88 --------
89
89
90 Get's an user by username, Returns empty result if user is not found.
90 Get's an user by username or user_id, Returns empty result if user is not found.
91 This command can be executed only using api_key belonging to user with admin
91 This command can be executed only using api_key belonging to user with admin
92 rights.
92 rights.
93
93
94
94
95 INPUT::
95 INPUT::
96
96
97 api_key : "<api_key>"
97 api_key : "<api_key>"
98 method : "get_user"
98 method : "get_user"
99 args : {
99 args : {
100 "username" : "<username>"
100 "userid" : "<username or user_id>"
101 }
101 }
102
102
103 OUTPUT::
103 OUTPUT::
104
104
105 result: None if user does not exist or
105 result: None if user does not exist or
106 {
106 {
107 "id" : "<id>",
107 "id" : "<id>",
108 "username" : "<username>",
108 "username" : "<username>",
109 "firstname": "<firstname>",
109 "firstname": "<firstname>",
110 "lastname" : "<lastname>",
110 "lastname" : "<lastname>",
111 "email" : "<email>",
111 "email" : "<email>",
112 "active" : "<bool>",
112 "active" : "<bool>",
113 "admin" :Β  "<bool>",
113 "admin" :Β  "<bool>",
114 "ldap_dn" : "<ldap_dn>"
114 "ldap_dn" : "<ldap_dn>"
115 }
115 }
116
116
117 error: null
117 error: null
118
118
119
119
120 get_users
120 get_users
121 ---------
121 ---------
122
122
123 Lists all existing users. This command can be executed only using api_key
123 Lists all existing users. This command can be executed only using api_key
124 belonging to user with admin rights.
124 belonging to user with admin rights.
125
125
126
126
127 INPUT::
127 INPUT::
128
128
129 api_key : "<api_key>"
129 api_key : "<api_key>"
130 method : "get_users"
130 method : "get_users"
131 args : { }
131 args : { }
132
132
133 OUTPUT::
133 OUTPUT::
134
134
135 result: [
135 result: [
136 {
136 {
137 "id" : "<id>",
137 "id" : "<id>",
138 "username" : "<username>",
138 "username" : "<username>",
139 "firstname": "<firstname>",
139 "firstname": "<firstname>",
140 "lastname" : "<lastname>",
140 "lastname" : "<lastname>",
141 "email" : "<email>",
141 "email" : "<email>",
142 "active" : "<bool>",
142 "active" : "<bool>",
143 "admin" :Β  "<bool>",
143 "admin" :Β  "<bool>",
144 "ldap_dn" : "<ldap_dn>"
144 "ldap_dn" : "<ldap_dn>"
145 },
145 },
146 …
146 …
147 ]
147 ]
148 error: null
148 error: null
149
149
150
150
151 create_user
151 create_user
152 -----------
152 -----------
153
153
154 Creates new user. This command can
154 Creates new user. This command can
155 be executed only using api_key belonging to user with admin rights.
155 be executed only using api_key belonging to user with admin rights.
156
156
157
157
158 INPUT::
158 INPUT::
159
159
160 api_key : "<api_key>"
160 api_key : "<api_key>"
161 method : "create_user"
161 method : "create_user"
162 args : {
162 args : {
163 "username" : "<username>",
163 "username" : "<username>",
164 "password" : "<password>",
164 "password" : "<password>",
165 "email" : "<useremail>",
165 "email" : "<useremail>",
166 "firstname" : "<firstname> = None",
166 "firstname" : "<firstname> = None",
167 "lastname" : "<lastname> = None",
167 "lastname" : "<lastname> = None",
168 "active" : "<bool> = True",
168 "active" : "<bool> = True",
169 "admin" : "<bool> = False",
169 "admin" : "<bool> = False",
170 "ldap_dn" : "<ldap_dn> = None"
170 "ldap_dn" : "<ldap_dn> = None"
171 }
171 }
172
172
173 OUTPUT::
173 OUTPUT::
174
174
175 result: {
175 result: {
176 "id" : "<new_user_id>",
176 "id" : "<new_user_id>",
177 "msg" : "created new user <username>"
177 "msg" : "created new user <username>"
178 }
178 }
179 error: null
179 error: null
180
180
181
181
182 update_user
182 update_user
183 -----------
183 -----------
184
184
185 updates current one if such user exists. This command can
185 updates current one if such user exists. This command can
186 be executed only using api_key belonging to user with admin rights.
186 be executed only using api_key belonging to user with admin rights.
187
187
188
188
189 INPUT::
189 INPUT::
190
190
191 api_key : "<api_key>"
191 api_key : "<api_key>"
192 method : "update_user"
192 method : "update_user"
193 args : {
193 args : {
194 "userid" : "<user_id or username>",
194 "userid" : "<user_id or username>",
195 "username" : "<username>",
195 "username" : "<username>",
196 "password" : "<password>",
196 "password" : "<password>",
197 "email" : "<useremail>",
197 "email" : "<useremail>",
198 "firstname" : "<firstname>",
198 "firstname" : "<firstname>",
199 "lastname" : "<lastname>",
199 "lastname" : "<lastname>",
200 "active" : "<bool>",
200 "active" : "<bool>",
201 "admin" : "<bool>",
201 "admin" : "<bool>",
202 "ldap_dn" : "<ldap_dn>"
202 "ldap_dn" : "<ldap_dn>"
203 }
203 }
204
204
205 OUTPUT::
205 OUTPUT::
206
206
207 result: {
207 result: {
208 "id" : "<edited_user_id>",
208 "id" : "<edited_user_id>",
209 "msg" : "updated user <username>"
209 "msg" : "updated user <username>"
210 }
210 }
211 error: null
211 error: null
212
212
213
213
214 get_users_group
214 get_users_group
215 ---------------
215 ---------------
216
216
217 Gets an existing users group. This command can be executed only using api_key
217 Gets an existing users group. This command can be executed only using api_key
218 belonging to user with admin rights.
218 belonging to user with admin rights.
219
219
220
220
221 INPUT::
221 INPUT::
222
222
223 api_key : "<api_key>"
223 api_key : "<api_key>"
224 method : "get_users_group"
224 method : "get_users_group"
225 args : {
225 args : {
226 "group_name" : "<name>"
226 "group_name" : "<name>"
227 }
227 }
228
228
229 OUTPUT::
229 OUTPUT::
230
230
231 result : None if group not exist
231 result : None if group not exist
232 {
232 {
233 "id" : "<id>",
233 "id" : "<id>",
234 "group_name" : "<groupname>",
234 "group_name" : "<groupname>",
235 "active": "<bool>",
235 "active": "<bool>",
236 "members" : [
236 "members" : [
237 { "id" : "<userid>",
237 { "id" : "<userid>",
238 "username" : "<username>",
238 "username" : "<username>",
239 "firstname": "<firstname>",
239 "firstname": "<firstname>",
240 "lastname" : "<lastname>",
240 "lastname" : "<lastname>",
241 "email" : "<email>",
241 "email" : "<email>",
242 "active" : "<bool>",
242 "active" : "<bool>",
243 "admin" :Β  "<bool>",
243 "admin" :Β  "<bool>",
244 "ldap" : "<ldap_dn>"
244 "ldap" : "<ldap_dn>"
245 },
245 },
246 …
246 …
247 ]
247 ]
248 }
248 }
249 error : null
249 error : null
250
250
251
251
252 get_users_groups
252 get_users_groups
253 ----------------
253 ----------------
254
254
255 Lists all existing users groups. This command can be executed only using
255 Lists all existing users groups. This command can be executed only using
256 api_key belonging to user with admin rights.
256 api_key belonging to user with admin rights.
257
257
258
258
259 INPUT::
259 INPUT::
260
260
261 api_key : "<api_key>"
261 api_key : "<api_key>"
262 method : "get_users_groups"
262 method : "get_users_groups"
263 args : { }
263 args : { }
264
264
265 OUTPUT::
265 OUTPUT::
266
266
267 result : [
267 result : [
268 {
268 {
269 "id" : "<id>",
269 "id" : "<id>",
270 "group_name" : "<groupname>",
270 "group_name" : "<groupname>",
271 "active": "<bool>",
271 "active": "<bool>",
272 "members" : [
272 "members" : [
273 {
273 {
274 "id" : "<userid>",
274 "id" : "<userid>",
275 "username" : "<username>",
275 "username" : "<username>",
276 "firstname": "<firstname>",
276 "firstname": "<firstname>",
277 "lastname" : "<lastname>",
277 "lastname" : "<lastname>",
278 "email" : "<email>",
278 "email" : "<email>",
279 "active" : "<bool>",
279 "active" : "<bool>",
280 "admin" :Β  "<bool>",
280 "admin" :Β  "<bool>",
281 "ldap" : "<ldap_dn>"
281 "ldap" : "<ldap_dn>"
282 },
282 },
283 …
283 …
284 ]
284 ]
285 }
285 }
286 ]
286 ]
287 error : null
287 error : null
288
288
289
289
290 create_users_group
290 create_users_group
291 ------------------
291 ------------------
292
292
293 Creates new users group. This command can be executed only using api_key
293 Creates new users group. This command can be executed only using api_key
294 belonging to user with admin rights
294 belonging to user with admin rights
295
295
296
296
297 INPUT::
297 INPUT::
298
298
299 api_key : "<api_key>"
299 api_key : "<api_key>"
300 method : "create_users_group"
300 method : "create_users_group"
301 args: {
301 args: {
302 "group_name": "<groupname>",
302 "group_name": "<groupname>",
303 "active":"<bool> = True"
303 "active":"<bool> = True"
304 }
304 }
305
305
306 OUTPUT::
306 OUTPUT::
307
307
308 result: {
308 result: {
309 "id": "<newusersgroupid>",
309 "id": "<newusersgroupid>",
310 "msg": "created new users group <groupname>"
310 "msg": "created new users group <groupname>"
311 }
311 }
312 error: null
312 error: null
313
313
314
314
315 add_user_to_users_group
315 add_user_to_users_group
316 -----------------------
316 -----------------------
317
317
318 Adds a user to a users group. If user exists in that group success will be
318 Adds a user to a users group. If user exists in that group success will be
319 `false`. This command can be executed only using api_key
319 `false`. This command can be executed only using api_key
320 belonging to user with admin rights
320 belonging to user with admin rights
321
321
322
322
323 INPUT::
323 INPUT::
324
324
325 api_key : "<api_key>"
325 api_key : "<api_key>"
326 method : "add_user_users_group"
326 method : "add_user_users_group"
327 args: {
327 args: {
328 "group_name" : "<groupname>",
328 "group_name" : "<groupname>",
329 "username" : "<username>"
329 "username" : "<username>"
330 }
330 }
331
331
332 OUTPUT::
332 OUTPUT::
333
333
334 result: {
334 result: {
335 "id": "<newusersgroupmemberid>",
335 "id": "<newusersgroupmemberid>",
336 "success": True|False # depends on if member is in group
336 "success": True|False # depends on if member is in group
337 "msg": "added member <username> to users group <groupname> |
337 "msg": "added member <username> to users group <groupname> |
338 User is already in that group"
338 User is already in that group"
339 }
339 }
340 error: null
340 error: null
341
341
342
342
343 remove_user_from_users_group
343 remove_user_from_users_group
344 ----------------------------
344 ----------------------------
345
345
346 Removes a user from a users group. If user is not in given group success will
346 Removes a user from a users group. If user is not in given group success will
347 be `false`. This command can be executed only
347 be `false`. This command can be executed only
348 using api_key belonging to user with admin rights
348 using api_key belonging to user with admin rights
349
349
350
350
351 INPUT::
351 INPUT::
352
352
353 api_key : "<api_key>"
353 api_key : "<api_key>"
354 method : "remove_user_from_users_group"
354 method : "remove_user_from_users_group"
355 args: {
355 args: {
356 "group_name" : "<groupname>",
356 "group_name" : "<groupname>",
357 "username" : "<username>"
357 "username" : "<username>"
358 }
358 }
359
359
360 OUTPUT::
360 OUTPUT::
361
361
362 result: {
362 result: {
363 "success": True|False, # depends on if member is in group
363 "success": True|False, # depends on if member is in group
364 "msg": "removed member <username> from users group <groupname> |
364 "msg": "removed member <username> from users group <groupname> |
365 User wasn't in group"
365 User wasn't in group"
366 }
366 }
367 error: null
367 error: null
368
368
369
369
370 get_repo
370 get_repo
371 --------
371 --------
372
372
373 Gets an existing repository. This command can be executed only using api_key
373 Gets an existing repository by it's name or repository_id. This command can
374 belonging to user with admin rights
374 be executed only using api_key belonging to user with admin rights.
375
375
376
376
377 INPUT::
377 INPUT::
378
378
379 api_key : "<api_key>"
379 api_key : "<api_key>"
380 method : "get_repo"
380 method : "get_repo"
381 args: {
381 args: {
382 "repo_name" : "<reponame>"
382 "repoid" : "<reponame or repo_id>"
383 }
383 }
384
384
385 OUTPUT::
385 OUTPUT::
386
386
387 result: None if repository does not exist or
387 result: None if repository does not exist or
388 {
388 {
389 "id" : "<id>",
389 "id" : "<id>",
390 "repo_name" : "<reponame>"
390 "repo_name" : "<reponame>"
391 "type" : "<type>",
391 "type" : "<type>",
392 "description" : "<description>",
392 "description" : "<description>",
393 "members" : [
393 "members" : [
394 { "id" : "<userid>",
394 { "id" : "<userid>",
395 "username" : "<username>",
395 "username" : "<username>",
396 "firstname": "<firstname>",
396 "firstname": "<firstname>",
397 "lastname" : "<lastname>",
397 "lastname" : "<lastname>",
398 "email" : "<email>",
398 "email" : "<email>",
399 "active" : "<bool>",
399 "active" : "<bool>",
400 "admin" :Β  "<bool>",
400 "admin" :Β  "<bool>",
401 "ldap" : "<ldap_dn>",
401 "ldap" : "<ldap_dn>",
402 "permission" : "repository.(read|write|admin)"
402 "permission" : "repository.(read|write|admin)"
403 },
403 },
404 …
404 …
405 {
405 {
406 "id" : "<usersgroupid>",
406 "id" : "<usersgroupid>",
407 "name" : "<usersgroupname>",
407 "name" : "<usersgroupname>",
408 "active": "<bool>",
408 "active": "<bool>",
409 "permission" : "repository.(read|write|admin)"
409 "permission" : "repository.(read|write|admin)"
410 },
410 },
411 …
411 …
412 ]
412 ]
413 }
413 }
414 error: null
414 error: null
415
415
416
416
417 get_repos
417 get_repos
418 ---------
418 ---------
419
419
420 Lists all existing repositories. This command can be executed only using api_key
420 Lists all existing repositories. This command can be executed only using api_key
421 belonging to user with admin rights
421 belonging to user with admin rights
422
422
423
423
424 INPUT::
424 INPUT::
425
425
426 api_key : "<api_key>"
426 api_key : "<api_key>"
427 method : "get_repos"
427 method : "get_repos"
428 args: { }
428 args: { }
429
429
430 OUTPUT::
430 OUTPUT::
431
431
432 result: [
432 result: [
433 {
433 {
434 "id" : "<id>",
434 "id" : "<id>",
435 "repo_name" : "<reponame>"
435 "repo_name" : "<reponame>"
436 "type" : "<type>",
436 "type" : "<type>",
437 "description" : "<description>"
437 "description" : "<description>"
438 },
438 },
439 …
439 …
440 ]
440 ]
441 error: null
441 error: null
442
442
443
443
444 get_repo_nodes
444 get_repo_nodes
445 --------------
445 --------------
446
446
447 returns a list of nodes and it's children in a flat list for a given path
447 returns a list of nodes and it's children in a flat list for a given path
448 at given revision. It's possible to specify ret_type to show only `files` or
448 at given revision. It's possible to specify ret_type to show only `files` or
449 `dirs`. This command can be executed only using api_key belonging to user
449 `dirs`. This command can be executed only using api_key belonging to user
450 with admin rights
450 with admin rights
451
451
452
452
453 INPUT::
453 INPUT::
454
454
455 api_key : "<api_key>"
455 api_key : "<api_key>"
456 method : "get_repo_nodes"
456 method : "get_repo_nodes"
457 args: {
457 args: {
458 "repo_name" : "<reponame>",
458 "repo_name" : "<reponame>",
459 "revision" : "<revision>",
459 "revision" : "<revision>",
460 "root_path" : "<root_path>",
460 "root_path" : "<root_path>",
461 "ret_type" : "<ret_type>" = 'all'
461 "ret_type" : "<ret_type>" = 'all'
462 }
462 }
463
463
464 OUTPUT::
464 OUTPUT::
465
465
466 result: [
466 result: [
467 {
467 {
468 "name" : "<name>"
468 "name" : "<name>"
469 "type" : "<type>",
469 "type" : "<type>",
470 },
470 },
471 …
471 …
472 ]
472 ]
473 error: null
473 error: null
474
474
475
475
476 create_repo
476 create_repo
477 -----------
477 -----------
478
478
479 Creates a repository. This command can be executed only using api_key
479 Creates a repository. This command can be executed only using api_key
480 belonging to user with admin rights.
480 belonging to user with admin rights.
481 If repository name contains "/", all needed repository groups will be created.
481 If repository name contains "/", all needed repository groups will be created.
482 For example "foo/bar/baz" will create groups "foo", "bar" (with "foo" as parent),
482 For example "foo/bar/baz" will create groups "foo", "bar" (with "foo" as parent),
483 and create "baz" repository with "bar" as group.
483 and create "baz" repository with "bar" as group.
484
484
485
485
486 INPUT::
486 INPUT::
487
487
488 api_key : "<api_key>"
488 api_key : "<api_key>"
489 method : "create_repo"
489 method : "create_repo"
490 args: {
490 args: {
491 "repo_name" : "<reponame>",
491 "repo_name" : "<reponame>",
492 "owner_name" : "<ownername>",
492 "owner_name" : "<ownername>",
493 "description" : "<description> = ''",
493 "description" : "<description> = ''",
494 "repo_type" : "<type> = 'hg'",
494 "repo_type" : "<type> = 'hg'",
495 "private" : "<bool> = False",
495 "private" : "<bool> = False",
496 "clone_uri" : "<clone_uri> = None",
496 "clone_uri" : "<clone_uri> = None",
497 }
497 }
498
498
499 OUTPUT::
499 OUTPUT::
500
500
501 result: {
501 result: {
502 "id": "<newrepoid>",
502 "id": "<newrepoid>",
503 "msg": "Created new repository <reponame>",
503 "msg": "Created new repository <reponame>",
504 }
504 }
505 error: null
505 error: null
506
506
507
507
508 delete_repo
508 delete_repo
509 -----------
509 -----------
510
510
511 Deletes a repository. This command can be executed only using api_key
511 Deletes a repository. This command can be executed only using api_key
512 belonging to user with admin rights.
512 belonging to user with admin rights.
513
513
514
514
515 INPUT::
515 INPUT::
516
516
517 api_key : "<api_key>"
517 api_key : "<api_key>"
518 method : "delete_repo"
518 method : "delete_repo"
519 args: {
519 args: {
520 "repo_name" : "<reponame>",
520 "repo_name" : "<reponame>",
521 }
521 }
522
522
523 OUTPUT::
523 OUTPUT::
524
524
525 result: {
525 result: {
526 "msg": "Deleted repository <reponame>",
526 "msg": "Deleted repository <reponame>",
527 }
527 }
528 error: null
528 error: null
529
529
530
530
531 grant_user_permission
531 grant_user_permission
532 ---------------------
532 ---------------------
533
533
534 Grant permission for user on given repository, or update existing one
534 Grant permission for user on given repository, or update existing one
535 if found. This command can be executed only using api_key belonging to user
535 if found. This command can be executed only using api_key belonging to user
536 with admin rights.
536 with admin rights.
537
537
538
538
539 INPUT::
539 INPUT::
540
540
541 api_key : "<api_key>"
541 api_key : "<api_key>"
542 method : "grant_user_permission"
542 method : "grant_user_permission"
543 args: {
543 args: {
544 "repo_name" : "<reponame>",
544 "repo_name" : "<reponame>",
545 "username" : "<username>",
545 "username" : "<username>",
546 "perm" : "(repository.(none|read|write|admin))",
546 "perm" : "(repository.(none|read|write|admin))",
547 }
547 }
548
548
549 OUTPUT::
549 OUTPUT::
550
550
551 result: {
551 result: {
552 "msg" : "Granted perm: <perm> for user: <username> in repo: <reponame>"
552 "msg" : "Granted perm: <perm> for user: <username> in repo: <reponame>"
553 }
553 }
554 error: null
554 error: null
555
555
556
556
557 revoke_user_permission
557 revoke_user_permission
558 ----------------------
558 ----------------------
559
559
560 Revoke permission for user on given repository. This command can be executed
560 Revoke permission for user on given repository. This command can be executed
561 only using api_key belonging to user with admin rights.
561 only using api_key belonging to user with admin rights.
562
562
563
563
564 INPUT::
564 INPUT::
565
565
566 api_key : "<api_key>"
566 api_key : "<api_key>"
567 method : "revoke_user_permission"
567 method : "revoke_user_permission"
568 args: {
568 args: {
569 "repo_name" : "<reponame>",
569 "repo_name" : "<reponame>",
570 "username" : "<username>",
570 "username" : "<username>",
571 }
571 }
572
572
573 OUTPUT::
573 OUTPUT::
574
574
575 result: {
575 result: {
576 "msg" : "Revoked perm for user: <suername> in repo: <reponame>"
576 "msg" : "Revoked perm for user: <suername> in repo: <reponame>"
577 }
577 }
578 error: null
578 error: null
579
579
580
580
581 grant_users_group_permission
581 grant_users_group_permission
582 ----------------------------
582 ----------------------------
583
583
584 Grant permission for users group on given repository, or update
584 Grant permission for users group on given repository, or update
585 existing one if found. This command can be executed only using
585 existing one if found. This command can be executed only using
586 api_key belonging to user with admin rights.
586 api_key belonging to user with admin rights.
587
587
588
588
589 INPUT::
589 INPUT::
590
590
591 api_key : "<api_key>"
591 api_key : "<api_key>"
592 method : "grant_users_group_permission"
592 method : "grant_users_group_permission"
593 args: {
593 args: {
594 "repo_name" : "<reponame>",
594 "repo_name" : "<reponame>",
595 "group_name" : "<usersgroupname>",
595 "group_name" : "<usersgroupname>",
596 "perm" : "(repository.(none|read|write|admin))",
596 "perm" : "(repository.(none|read|write|admin))",
597 }
597 }
598
598
599 OUTPUT::
599 OUTPUT::
600
600
601 result: {
601 result: {
602 "msg" : "Granted perm: <perm> for group: <usersgroupname> in repo: <reponame>"
602 "msg" : "Granted perm: <perm> for group: <usersgroupname> in repo: <reponame>"
603 }
603 }
604 error: null
604 error: null
605
605
606
606
607 revoke_users_group_permission
607 revoke_users_group_permission
608 -----------------------------
608 -----------------------------
609
609
610 Revoke permission for users group on given repository.This command can be
610 Revoke permission for users group on given repository.This command can be
611 executed only using api_key belonging to user with admin rights.
611 executed only using api_key belonging to user with admin rights.
612
612
613 INPUT::
613 INPUT::
614
614
615 api_key : "<api_key>"
615 api_key : "<api_key>"
616 method : "revoke_users_group_permission"
616 method : "revoke_users_group_permission"
617 args: {
617 args: {
618 "repo_name" : "<reponame>",
618 "repo_name" : "<reponame>",
619 "users_group" : "<usersgroupname>",
619 "users_group" : "<usersgroupname>",
620 }
620 }
621
621
622 OUTPUT::
622 OUTPUT::
623
623
624 result: {
624 result: {
625 "msg" : "Revoked perm for group: <usersgroupname> in repo: <reponame>"
625 "msg" : "Revoked perm for group: <usersgroupname> in repo: <reponame>"
626 }
626 }
627 error: null No newline at end of file
627 error: null
@@ -1,660 +1,660 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.api
3 rhodecode.controllers.api
4 ~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 API controller for RhodeCode
6 API controller for RhodeCode
7
7
8 :created_on: Aug 20, 2011
8 :created_on: Aug 20, 2011
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software; you can redistribute it and/or
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
16 # of the License or (at your opinion) any later version of the license.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
26 # MA 02110-1301, USA.
27
27
28 import traceback
28 import traceback
29 import logging
29 import logging
30
30
31 from rhodecode.controllers.api import JSONRPCController, JSONRPCError
31 from rhodecode.controllers.api import JSONRPCController, JSONRPCError
32 from rhodecode.lib.auth import HasPermissionAllDecorator, \
32 from rhodecode.lib.auth import HasPermissionAllDecorator, \
33 HasPermissionAnyDecorator, PasswordGenerator
33 HasPermissionAnyDecorator, PasswordGenerator
34
34
35 from rhodecode.model.meta import Session
35 from rhodecode.model.meta import Session
36 from rhodecode.model.scm import ScmModel
36 from rhodecode.model.scm import ScmModel
37 from rhodecode.model.db import User, UsersGroup, RepoGroup, Repository
37 from rhodecode.model.db import User, UsersGroup, RepoGroup, Repository
38 from rhodecode.model.repo import RepoModel
38 from rhodecode.model.repo import RepoModel
39 from rhodecode.model.user import UserModel
39 from rhodecode.model.user import UserModel
40 from rhodecode.model.users_group import UsersGroupModel
40 from rhodecode.model.users_group import UsersGroupModel
41 from rhodecode.model.repos_group import ReposGroupModel
41 from rhodecode.model.repos_group import ReposGroupModel
42
42
43
43
44 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
45
45
46
46
47 class ApiController(JSONRPCController):
47 class ApiController(JSONRPCController):
48 """
48 """
49 API Controller
49 API Controller
50
50
51
51
52 Each method needs to have USER as argument this is then based on given
52 Each method needs to have USER as argument this is then based on given
53 API_KEY propagated as instance of user object
53 API_KEY propagated as instance of user object
54
54
55 Preferably this should be first argument also
55 Preferably this should be first argument also
56
56
57
57
58 Each function should also **raise** JSONRPCError for any
58 Each function should also **raise** JSONRPCError for any
59 errors that happens
59 errors that happens
60
60
61 """
61 """
62
62
63 @HasPermissionAllDecorator('hg.admin')
63 @HasPermissionAllDecorator('hg.admin')
64 def pull(self, apiuser, repo_name):
64 def pull(self, apiuser, repo_name):
65 """
65 """
66 Dispatch pull action on given repo
66 Dispatch pull action on given repo
67
67
68
68
69 :param user:
69 :param user:
70 :param repo_name:
70 :param repo_name:
71 """
71 """
72
72
73 if Repository.is_valid(repo_name) is False:
73 if Repository.is_valid(repo_name) is False:
74 raise JSONRPCError('Unknown repo "%s"' % repo_name)
74 raise JSONRPCError('Unknown repo "%s"' % repo_name)
75
75
76 try:
76 try:
77 ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
77 ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
78 return 'Pulled from %s' % repo_name
78 return 'Pulled from %s' % repo_name
79 except Exception:
79 except Exception:
80 raise JSONRPCError('Unable to pull changes from "%s"' % repo_name)
80 raise JSONRPCError('Unable to pull changes from "%s"' % repo_name)
81
81
82 @HasPermissionAllDecorator('hg.admin')
82 @HasPermissionAllDecorator('hg.admin')
83 def get_user(self, apiuser, username):
83 def get_user(self, apiuser, userid):
84 """"
84 """"
85 Get a user by username
85 Get a user by username
86
86
87 :param apiuser:
87 :param apiuser:
88 :param username:
88 :param username:
89 """
89 """
90
90
91 user = User.get_by_username(username)
91 user = UserModel().get_user(userid)
92 if user is None:
92 if user is None:
93 return user
93 return user
94
94
95 return dict(
95 return dict(
96 id=user.user_id,
96 id=user.user_id,
97 username=user.username,
97 username=user.username,
98 firstname=user.name,
98 firstname=user.name,
99 lastname=user.lastname,
99 lastname=user.lastname,
100 email=user.email,
100 email=user.email,
101 active=user.active,
101 active=user.active,
102 admin=user.admin,
102 admin=user.admin,
103 ldap_dn=user.ldap_dn
103 ldap_dn=user.ldap_dn
104 )
104 )
105
105
106 @HasPermissionAllDecorator('hg.admin')
106 @HasPermissionAllDecorator('hg.admin')
107 def get_users(self, apiuser):
107 def get_users(self, apiuser):
108 """"
108 """"
109 Get all users
109 Get all users
110
110
111 :param apiuser:
111 :param apiuser:
112 """
112 """
113
113
114 result = []
114 result = []
115 for user in User.getAll():
115 for user in User.getAll():
116 result.append(
116 result.append(
117 dict(
117 dict(
118 id=user.user_id,
118 id=user.user_id,
119 username=user.username,
119 username=user.username,
120 firstname=user.name,
120 firstname=user.name,
121 lastname=user.lastname,
121 lastname=user.lastname,
122 email=user.email,
122 email=user.email,
123 active=user.active,
123 active=user.active,
124 admin=user.admin,
124 admin=user.admin,
125 ldap_dn=user.ldap_dn
125 ldap_dn=user.ldap_dn
126 )
126 )
127 )
127 )
128 return result
128 return result
129
129
130 @HasPermissionAllDecorator('hg.admin')
130 @HasPermissionAllDecorator('hg.admin')
131 def create_user(self, apiuser, username, email, password, firstname=None,
131 def create_user(self, apiuser, username, email, password, firstname=None,
132 lastname=None, active=True, admin=False, ldap_dn=None):
132 lastname=None, active=True, admin=False, ldap_dn=None):
133 """
133 """
134 Create new user
134 Create new user
135
135
136 :param apiuser:
136 :param apiuser:
137 :param username:
137 :param username:
138 :param password:
138 :param password:
139 :param email:
139 :param email:
140 :param name:
140 :param name:
141 :param lastname:
141 :param lastname:
142 :param active:
142 :param active:
143 :param admin:
143 :param admin:
144 :param ldap_dn:
144 :param ldap_dn:
145 """
145 """
146 if User.get_by_username(username):
146 if User.get_by_username(username):
147 raise JSONRPCError("user %s already exist" % username)
147 raise JSONRPCError("user %s already exist" % username)
148
148
149 if User.get_by_email(email, case_insensitive=True):
149 if User.get_by_email(email, case_insensitive=True):
150 raise JSONRPCError("email %s already exist" % email)
150 raise JSONRPCError("email %s already exist" % email)
151
151
152 if ldap_dn:
152 if ldap_dn:
153 # generate temporary password if ldap_dn
153 # generate temporary password if ldap_dn
154 password = PasswordGenerator().gen_password(length=8)
154 password = PasswordGenerator().gen_password(length=8)
155
155
156 try:
156 try:
157 usr = UserModel().create_or_update(
157 usr = UserModel().create_or_update(
158 username, password, email, firstname,
158 username, password, email, firstname,
159 lastname, active, admin, ldap_dn
159 lastname, active, admin, ldap_dn
160 )
160 )
161 Session.commit()
161 Session.commit()
162 return dict(
162 return dict(
163 id=usr.user_id,
163 id=usr.user_id,
164 msg='created new user %s' % username
164 msg='created new user %s' % username
165 )
165 )
166 except Exception:
166 except Exception:
167 log.error(traceback.format_exc())
167 log.error(traceback.format_exc())
168 raise JSONRPCError('failed to create user %s' % username)
168 raise JSONRPCError('failed to create user %s' % username)
169
169
170 @HasPermissionAllDecorator('hg.admin')
170 @HasPermissionAllDecorator('hg.admin')
171 def update_user(self, apiuser, userid, username, password, email,
171 def update_user(self, apiuser, userid, username, password, email,
172 firstname, lastname, active, admin, ldap_dn):
172 firstname, lastname, active, admin, ldap_dn):
173 """
173 """
174 Updates given user
174 Updates given user
175
175
176 :param apiuser:
176 :param apiuser:
177 :param username:
177 :param username:
178 :param password:
178 :param password:
179 :param email:
179 :param email:
180 :param name:
180 :param name:
181 :param lastname:
181 :param lastname:
182 :param active:
182 :param active:
183 :param admin:
183 :param admin:
184 :param ldap_dn:
184 :param ldap_dn:
185 """
185 """
186 if not UserModel().get_user(userid):
186 if not UserModel().get_user(userid):
187 raise JSONRPCError("user %s does not exist" % username)
187 raise JSONRPCError("user %s does not exist" % username)
188
188
189 try:
189 try:
190 usr = UserModel().create_or_update(
190 usr = UserModel().create_or_update(
191 username, password, email, firstname,
191 username, password, email, firstname,
192 lastname, active, admin, ldap_dn
192 lastname, active, admin, ldap_dn
193 )
193 )
194 Session.commit()
194 Session.commit()
195 return dict(
195 return dict(
196 id=usr.user_id,
196 id=usr.user_id,
197 msg='updated user %s' % username
197 msg='updated user %s' % username
198 )
198 )
199 except Exception:
199 except Exception:
200 log.error(traceback.format_exc())
200 log.error(traceback.format_exc())
201 raise JSONRPCError('failed to update user %s' % username)
201 raise JSONRPCError('failed to update user %s' % username)
202
202
203 @HasPermissionAllDecorator('hg.admin')
203 @HasPermissionAllDecorator('hg.admin')
204 def get_users_group(self, apiuser, group_name):
204 def get_users_group(self, apiuser, group_name):
205 """"
205 """"
206 Get users group by name
206 Get users group by name
207
207
208 :param apiuser:
208 :param apiuser:
209 :param group_name:
209 :param group_name:
210 """
210 """
211
211
212 users_group = UsersGroup.get_by_group_name(group_name)
212 users_group = UsersGroup.get_by_group_name(group_name)
213 if not users_group:
213 if not users_group:
214 return None
214 return None
215
215
216 members = []
216 members = []
217 for user in users_group.members:
217 for user in users_group.members:
218 user = user.user
218 user = user.user
219 members.append(dict(id=user.user_id,
219 members.append(dict(id=user.user_id,
220 username=user.username,
220 username=user.username,
221 firstname=user.name,
221 firstname=user.name,
222 lastname=user.lastname,
222 lastname=user.lastname,
223 email=user.email,
223 email=user.email,
224 active=user.active,
224 active=user.active,
225 admin=user.admin,
225 admin=user.admin,
226 ldap=user.ldap_dn))
226 ldap=user.ldap_dn))
227
227
228 return dict(id=users_group.users_group_id,
228 return dict(id=users_group.users_group_id,
229 group_name=users_group.users_group_name,
229 group_name=users_group.users_group_name,
230 active=users_group.users_group_active,
230 active=users_group.users_group_active,
231 members=members)
231 members=members)
232
232
233 @HasPermissionAllDecorator('hg.admin')
233 @HasPermissionAllDecorator('hg.admin')
234 def get_users_groups(self, apiuser):
234 def get_users_groups(self, apiuser):
235 """"
235 """"
236 Get all users groups
236 Get all users groups
237
237
238 :param apiuser:
238 :param apiuser:
239 """
239 """
240
240
241 result = []
241 result = []
242 for users_group in UsersGroup.getAll():
242 for users_group in UsersGroup.getAll():
243 members = []
243 members = []
244 for user in users_group.members:
244 for user in users_group.members:
245 user = user.user
245 user = user.user
246 members.append(dict(id=user.user_id,
246 members.append(dict(id=user.user_id,
247 username=user.username,
247 username=user.username,
248 firstname=user.name,
248 firstname=user.name,
249 lastname=user.lastname,
249 lastname=user.lastname,
250 email=user.email,
250 email=user.email,
251 active=user.active,
251 active=user.active,
252 admin=user.admin,
252 admin=user.admin,
253 ldap=user.ldap_dn))
253 ldap=user.ldap_dn))
254
254
255 result.append(dict(id=users_group.users_group_id,
255 result.append(dict(id=users_group.users_group_id,
256 group_name=users_group.users_group_name,
256 group_name=users_group.users_group_name,
257 active=users_group.users_group_active,
257 active=users_group.users_group_active,
258 members=members))
258 members=members))
259 return result
259 return result
260
260
261 @HasPermissionAllDecorator('hg.admin')
261 @HasPermissionAllDecorator('hg.admin')
262 def create_users_group(self, apiuser, group_name, active=True):
262 def create_users_group(self, apiuser, group_name, active=True):
263 """
263 """
264 Creates an new usergroup
264 Creates an new usergroup
265
265
266 :param group_name:
266 :param group_name:
267 :param active:
267 :param active:
268 """
268 """
269
269
270 if self.get_users_group(apiuser, group_name):
270 if self.get_users_group(apiuser, group_name):
271 raise JSONRPCError("users group %s already exist" % group_name)
271 raise JSONRPCError("users group %s already exist" % group_name)
272
272
273 try:
273 try:
274 ug = UsersGroupModel().create(name=group_name, active=active)
274 ug = UsersGroupModel().create(name=group_name, active=active)
275 Session.commit()
275 Session.commit()
276 return dict(id=ug.users_group_id,
276 return dict(id=ug.users_group_id,
277 msg='created new users group %s' % group_name)
277 msg='created new users group %s' % group_name)
278 except Exception:
278 except Exception:
279 log.error(traceback.format_exc())
279 log.error(traceback.format_exc())
280 raise JSONRPCError('failed to create group %s' % group_name)
280 raise JSONRPCError('failed to create group %s' % group_name)
281
281
282 @HasPermissionAllDecorator('hg.admin')
282 @HasPermissionAllDecorator('hg.admin')
283 def add_user_to_users_group(self, apiuser, group_name, username):
283 def add_user_to_users_group(self, apiuser, group_name, username):
284 """"
284 """"
285 Add a user to a group
285 Add a user to a group
286
286
287 :param apiuser:
287 :param apiuser:
288 :param group_name:
288 :param group_name:
289 :param username:
289 :param username:
290 """
290 """
291
291
292 try:
292 try:
293 users_group = UsersGroup.get_by_group_name(group_name)
293 users_group = UsersGroup.get_by_group_name(group_name)
294 if not users_group:
294 if not users_group:
295 raise JSONRPCError('unknown users group %s' % group_name)
295 raise JSONRPCError('unknown users group %s' % group_name)
296
296
297 user = User.get_by_username(username)
297 user = User.get_by_username(username)
298 if user is None:
298 if user is None:
299 raise JSONRPCError('unknown user %s' % username)
299 raise JSONRPCError('unknown user %s' % username)
300
300
301 ugm = UsersGroupModel().add_user_to_group(users_group, user)
301 ugm = UsersGroupModel().add_user_to_group(users_group, user)
302 success = True if ugm != True else False
302 success = True if ugm != True else False
303 msg = 'added member %s to users group %s' % (username, group_name)
303 msg = 'added member %s to users group %s' % (username, group_name)
304 msg = msg if success else 'User is already in that group'
304 msg = msg if success else 'User is already in that group'
305 Session.commit()
305 Session.commit()
306
306
307 return dict(
307 return dict(
308 id=ugm.users_group_member_id if ugm != True else None,
308 id=ugm.users_group_member_id if ugm != True else None,
309 success=success,
309 success=success,
310 msg=msg
310 msg=msg
311 )
311 )
312 except Exception:
312 except Exception:
313 log.error(traceback.format_exc())
313 log.error(traceback.format_exc())
314 raise JSONRPCError('failed to add users group member')
314 raise JSONRPCError('failed to add users group member')
315
315
316 @HasPermissionAllDecorator('hg.admin')
316 @HasPermissionAllDecorator('hg.admin')
317 def remove_user_from_users_group(self, apiuser, group_name, username):
317 def remove_user_from_users_group(self, apiuser, group_name, username):
318 """
318 """
319 Remove user from a group
319 Remove user from a group
320
320
321 :param apiuser
321 :param apiuser
322 :param group_name
322 :param group_name
323 :param username
323 :param username
324 """
324 """
325
325
326 try:
326 try:
327 users_group = UsersGroup.get_by_group_name(group_name)
327 users_group = UsersGroup.get_by_group_name(group_name)
328 if not users_group:
328 if not users_group:
329 raise JSONRPCError('unknown users group %s' % group_name)
329 raise JSONRPCError('unknown users group %s' % group_name)
330
330
331 user = User.get_by_username(username)
331 user = User.get_by_username(username)
332 if user is None:
332 if user is None:
333 raise JSONRPCError('unknown user %s' % username)
333 raise JSONRPCError('unknown user %s' % username)
334
334
335 success = UsersGroupModel().remove_user_from_group(users_group, user)
335 success = UsersGroupModel().remove_user_from_group(users_group, user)
336 msg = 'removed member %s from users group %s' % (username, group_name)
336 msg = 'removed member %s from users group %s' % (username, group_name)
337 msg = msg if success else "User wasn't in group"
337 msg = msg if success else "User wasn't in group"
338 Session.commit()
338 Session.commit()
339 return dict(success=success, msg=msg)
339 return dict(success=success, msg=msg)
340 except Exception:
340 except Exception:
341 log.error(traceback.format_exc())
341 log.error(traceback.format_exc())
342 raise JSONRPCError('failed to remove user from group')
342 raise JSONRPCError('failed to remove user from group')
343
343
344 @HasPermissionAnyDecorator('hg.admin')
344 @HasPermissionAnyDecorator('hg.admin')
345 def get_repo(self, apiuser, repo_name):
345 def get_repo(self, apiuser, repoid):
346 """"
346 """"
347 Get repository by name
347 Get repository by name
348
348
349 :param apiuser:
349 :param apiuser:
350 :param repo_name:
350 :param repo_name:
351 """
351 """
352
352
353 repo = Repository.get_by_repo_name(repo_name)
353 repo = RepoModel().get_repo(repoid)
354 if repo is None:
354 if repo is None:
355 raise JSONRPCError('unknown repository %s' % repo)
355 raise JSONRPCError('unknown repository %s' % repo)
356
356
357 members = []
357 members = []
358 for user in repo.repo_to_perm:
358 for user in repo.repo_to_perm:
359 perm = user.permission.permission_name
359 perm = user.permission.permission_name
360 user = user.user
360 user = user.user
361 members.append(
361 members.append(
362 dict(
362 dict(
363 type_="user",
363 type_="user",
364 id=user.user_id,
364 id=user.user_id,
365 username=user.username,
365 username=user.username,
366 firstname=user.name,
366 firstname=user.name,
367 lastname=user.lastname,
367 lastname=user.lastname,
368 email=user.email,
368 email=user.email,
369 active=user.active,
369 active=user.active,
370 admin=user.admin,
370 admin=user.admin,
371 ldap=user.ldap_dn,
371 ldap=user.ldap_dn,
372 permission=perm
372 permission=perm
373 )
373 )
374 )
374 )
375 for users_group in repo.users_group_to_perm:
375 for users_group in repo.users_group_to_perm:
376 perm = users_group.permission.permission_name
376 perm = users_group.permission.permission_name
377 users_group = users_group.users_group
377 users_group = users_group.users_group
378 members.append(
378 members.append(
379 dict(
379 dict(
380 type_="users_group",
380 type_="users_group",
381 id=users_group.users_group_id,
381 id=users_group.users_group_id,
382 name=users_group.users_group_name,
382 name=users_group.users_group_name,
383 active=users_group.users_group_active,
383 active=users_group.users_group_active,
384 permission=perm
384 permission=perm
385 )
385 )
386 )
386 )
387
387
388 return dict(
388 return dict(
389 id=repo.repo_id,
389 id=repo.repo_id,
390 repo_name=repo.repo_name,
390 repo_name=repo.repo_name,
391 type=repo.repo_type,
391 type=repo.repo_type,
392 description=repo.description,
392 description=repo.description,
393 members=members
393 members=members
394 )
394 )
395
395
396 @HasPermissionAnyDecorator('hg.admin')
396 @HasPermissionAnyDecorator('hg.admin')
397 def get_repos(self, apiuser):
397 def get_repos(self, apiuser):
398 """"
398 """"
399 Get all repositories
399 Get all repositories
400
400
401 :param apiuser:
401 :param apiuser:
402 """
402 """
403
403
404 result = []
404 result = []
405 for repository in Repository.getAll():
405 for repository in Repository.getAll():
406 result.append(
406 result.append(
407 dict(
407 dict(
408 id=repository.repo_id,
408 id=repository.repo_id,
409 repo_name=repository.repo_name,
409 repo_name=repository.repo_name,
410 type=repository.repo_type,
410 type=repository.repo_type,
411 description=repository.description
411 description=repository.description
412 )
412 )
413 )
413 )
414 return result
414 return result
415
415
416 @HasPermissionAnyDecorator('hg.admin')
416 @HasPermissionAnyDecorator('hg.admin')
417 def get_repo_nodes(self, apiuser, repo_name, revision, root_path,
417 def get_repo_nodes(self, apiuser, repo_name, revision, root_path,
418 ret_type='all'):
418 ret_type='all'):
419 """
419 """
420 returns a list of nodes and it's children
420 returns a list of nodes and it's children
421 for a given path at given revision. It's possible to specify ret_type
421 for a given path at given revision. It's possible to specify ret_type
422 to show only files or dirs
422 to show only files or dirs
423
423
424 :param apiuser:
424 :param apiuser:
425 :param repo_name: name of repository
425 :param repo_name: name of repository
426 :param revision: revision for which listing should be done
426 :param revision: revision for which listing should be done
427 :param root_path: path from which start displaying
427 :param root_path: path from which start displaying
428 :param ret_type: return type 'all|files|dirs' nodes
428 :param ret_type: return type 'all|files|dirs' nodes
429 """
429 """
430 try:
430 try:
431 _d, _f = ScmModel().get_nodes(repo_name, revision, root_path,
431 _d, _f = ScmModel().get_nodes(repo_name, revision, root_path,
432 flat=False)
432 flat=False)
433 _map = {
433 _map = {
434 'all': _d + _f,
434 'all': _d + _f,
435 'files': _f,
435 'files': _f,
436 'dirs': _d,
436 'dirs': _d,
437 }
437 }
438 return _map[ret_type]
438 return _map[ret_type]
439 except KeyError:
439 except KeyError:
440 raise JSONRPCError('ret_type must be one of %s' % _map.keys())
440 raise JSONRPCError('ret_type must be one of %s' % _map.keys())
441 except Exception, e:
441 except Exception, e:
442 raise JSONRPCError(e)
442 raise JSONRPCError(e)
443
443
444 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
444 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
445 def create_repo(self, apiuser, repo_name, owner_name, description='',
445 def create_repo(self, apiuser, repo_name, owner_name, description='',
446 repo_type='hg', private=False, clone_uri=None):
446 repo_type='hg', private=False, clone_uri=None):
447 """
447 """
448 Create repository, if clone_url is given it makes a remote clone
448 Create repository, if clone_url is given it makes a remote clone
449
449
450 :param apiuser:
450 :param apiuser:
451 :param repo_name:
451 :param repo_name:
452 :param owner_name:
452 :param owner_name:
453 :param description:
453 :param description:
454 :param repo_type:
454 :param repo_type:
455 :param private:
455 :param private:
456 :param clone_uri:
456 :param clone_uri:
457 """
457 """
458
458
459 try:
459 try:
460 owner = User.get_by_username(owner_name)
460 owner = User.get_by_username(owner_name)
461 if owner is None:
461 if owner is None:
462 raise JSONRPCError('unknown user %s' % owner_name)
462 raise JSONRPCError('unknown user %s' % owner_name)
463
463
464 if Repository.get_by_repo_name(repo_name):
464 if Repository.get_by_repo_name(repo_name):
465 raise JSONRPCError("repo %s already exist" % repo_name)
465 raise JSONRPCError("repo %s already exist" % repo_name)
466
466
467 groups = repo_name.split('/')
467 groups = repo_name.split('/')
468 real_name = groups[-1]
468 real_name = groups[-1]
469 groups = groups[:-1]
469 groups = groups[:-1]
470 parent_id = None
470 parent_id = None
471 for g in groups:
471 for g in groups:
472 group = RepoGroup.get_by_group_name(g)
472 group = RepoGroup.get_by_group_name(g)
473 if not group:
473 if not group:
474 group = ReposGroupModel().create(g, '', parent_id)
474 group = ReposGroupModel().create(g, '', parent_id)
475 parent_id = group.group_id
475 parent_id = group.group_id
476
476
477 repo = RepoModel().create(
477 repo = RepoModel().create(
478 dict(
478 dict(
479 repo_name=real_name,
479 repo_name=real_name,
480 repo_name_full=repo_name,
480 repo_name_full=repo_name,
481 description=description,
481 description=description,
482 private=private,
482 private=private,
483 repo_type=repo_type,
483 repo_type=repo_type,
484 repo_group=parent_id,
484 repo_group=parent_id,
485 clone_uri=clone_uri
485 clone_uri=clone_uri
486 ),
486 ),
487 owner
487 owner
488 )
488 )
489 Session.commit()
489 Session.commit()
490
490
491 return dict(
491 return dict(
492 id=repo.repo_id,
492 id=repo.repo_id,
493 msg="Created new repository %s" % repo.repo_name
493 msg="Created new repository %s" % repo.repo_name
494 )
494 )
495
495
496 except Exception:
496 except Exception:
497 log.error(traceback.format_exc())
497 log.error(traceback.format_exc())
498 raise JSONRPCError('failed to create repository %s' % repo_name)
498 raise JSONRPCError('failed to create repository %s' % repo_name)
499
499
500 @HasPermissionAnyDecorator('hg.admin')
500 @HasPermissionAnyDecorator('hg.admin')
501 def delete_repo(self, apiuser, repo_name):
501 def delete_repo(self, apiuser, repo_name):
502 """
502 """
503 Deletes a given repository
503 Deletes a given repository
504
504
505 :param repo_name:
505 :param repo_name:
506 """
506 """
507 if not Repository.get_by_repo_name(repo_name):
507 if not Repository.get_by_repo_name(repo_name):
508 raise JSONRPCError("repo %s does not exist" % repo_name)
508 raise JSONRPCError("repo %s does not exist" % repo_name)
509 try:
509 try:
510 RepoModel().delete(repo_name)
510 RepoModel().delete(repo_name)
511 Session.commit()
511 Session.commit()
512 return dict(
512 return dict(
513 msg='Deleted repository %s' % repo_name
513 msg='Deleted repository %s' % repo_name
514 )
514 )
515 except Exception:
515 except Exception:
516 log.error(traceback.format_exc())
516 log.error(traceback.format_exc())
517 raise JSONRPCError('failed to delete repository %s' % repo_name)
517 raise JSONRPCError('failed to delete repository %s' % repo_name)
518
518
519 @HasPermissionAnyDecorator('hg.admin')
519 @HasPermissionAnyDecorator('hg.admin')
520 def grant_user_permission(self, apiuser, repo_name, username, perm):
520 def grant_user_permission(self, apiuser, repo_name, username, perm):
521 """
521 """
522 Grant permission for user on given repository, or update existing one
522 Grant permission for user on given repository, or update existing one
523 if found
523 if found
524
524
525 :param repo_name:
525 :param repo_name:
526 :param username:
526 :param username:
527 :param perm:
527 :param perm:
528 """
528 """
529
529
530 try:
530 try:
531 repo = Repository.get_by_repo_name(repo_name)
531 repo = Repository.get_by_repo_name(repo_name)
532 if repo is None:
532 if repo is None:
533 raise JSONRPCError('unknown repository %s' % repo)
533 raise JSONRPCError('unknown repository %s' % repo)
534
534
535 user = User.get_by_username(username)
535 user = User.get_by_username(username)
536 if user is None:
536 if user is None:
537 raise JSONRPCError('unknown user %s' % username)
537 raise JSONRPCError('unknown user %s' % username)
538
538
539 RepoModel().grant_user_permission(repo=repo, user=user, perm=perm)
539 RepoModel().grant_user_permission(repo=repo, user=user, perm=perm)
540
540
541 Session.commit()
541 Session.commit()
542 return dict(
542 return dict(
543 msg='Granted perm: %s for user: %s in repo: %s' % (
543 msg='Granted perm: %s for user: %s in repo: %s' % (
544 perm, username, repo_name
544 perm, username, repo_name
545 )
545 )
546 )
546 )
547 except Exception:
547 except Exception:
548 log.error(traceback.format_exc())
548 log.error(traceback.format_exc())
549 raise JSONRPCError(
549 raise JSONRPCError(
550 'failed to edit permission %(repo)s for %(user)s' % dict(
550 'failed to edit permission %(repo)s for %(user)s' % dict(
551 user=username, repo=repo_name
551 user=username, repo=repo_name
552 )
552 )
553 )
553 )
554
554
555 @HasPermissionAnyDecorator('hg.admin')
555 @HasPermissionAnyDecorator('hg.admin')
556 def revoke_user_permission(self, apiuser, repo_name, username):
556 def revoke_user_permission(self, apiuser, repo_name, username):
557 """
557 """
558 Revoke permission for user on given repository
558 Revoke permission for user on given repository
559
559
560 :param repo_name:
560 :param repo_name:
561 :param username:
561 :param username:
562 """
562 """
563
563
564 try:
564 try:
565 repo = Repository.get_by_repo_name(repo_name)
565 repo = Repository.get_by_repo_name(repo_name)
566 if repo is None:
566 if repo is None:
567 raise JSONRPCError('unknown repository %s' % repo)
567 raise JSONRPCError('unknown repository %s' % repo)
568
568
569 user = User.get_by_username(username)
569 user = User.get_by_username(username)
570 if user is None:
570 if user is None:
571 raise JSONRPCError('unknown user %s' % username)
571 raise JSONRPCError('unknown user %s' % username)
572
572
573 RepoModel().revoke_user_permission(repo=repo_name, user=username)
573 RepoModel().revoke_user_permission(repo=repo_name, user=username)
574
574
575 Session.commit()
575 Session.commit()
576 return dict(
576 return dict(
577 msg='Revoked perm for user: %s in repo: %s' % (
577 msg='Revoked perm for user: %s in repo: %s' % (
578 username, repo_name
578 username, repo_name
579 )
579 )
580 )
580 )
581 except Exception:
581 except Exception:
582 log.error(traceback.format_exc())
582 log.error(traceback.format_exc())
583 raise JSONRPCError(
583 raise JSONRPCError(
584 'failed to edit permission %(repo)s for %(user)s' % dict(
584 'failed to edit permission %(repo)s for %(user)s' % dict(
585 user=username, repo=repo_name
585 user=username, repo=repo_name
586 )
586 )
587 )
587 )
588
588
589 @HasPermissionAnyDecorator('hg.admin')
589 @HasPermissionAnyDecorator('hg.admin')
590 def grant_users_group_permission(self, apiuser, repo_name, group_name, perm):
590 def grant_users_group_permission(self, apiuser, repo_name, group_name, perm):
591 """
591 """
592 Grant permission for users group on given repository, or update
592 Grant permission for users group on given repository, or update
593 existing one if found
593 existing one if found
594
594
595 :param repo_name:
595 :param repo_name:
596 :param group_name:
596 :param group_name:
597 :param perm:
597 :param perm:
598 """
598 """
599
599
600 try:
600 try:
601 repo = Repository.get_by_repo_name(repo_name)
601 repo = Repository.get_by_repo_name(repo_name)
602 if repo is None:
602 if repo is None:
603 raise JSONRPCError('unknown repository %s' % repo)
603 raise JSONRPCError('unknown repository %s' % repo)
604
604
605 user_group = UsersGroup.get_by_group_name(group_name)
605 user_group = UsersGroup.get_by_group_name(group_name)
606 if user_group is None:
606 if user_group is None:
607 raise JSONRPCError('unknown users group %s' % user_group)
607 raise JSONRPCError('unknown users group %s' % user_group)
608
608
609 RepoModel().grant_users_group_permission(repo=repo_name,
609 RepoModel().grant_users_group_permission(repo=repo_name,
610 group_name=group_name,
610 group_name=group_name,
611 perm=perm)
611 perm=perm)
612
612
613 Session.commit()
613 Session.commit()
614 return dict(
614 return dict(
615 msg='Granted perm: %s for group: %s in repo: %s' % (
615 msg='Granted perm: %s for group: %s in repo: %s' % (
616 perm, group_name, repo_name
616 perm, group_name, repo_name
617 )
617 )
618 )
618 )
619 except Exception:
619 except Exception:
620 log.error(traceback.format_exc())
620 log.error(traceback.format_exc())
621 raise JSONRPCError(
621 raise JSONRPCError(
622 'failed to edit permission %(repo)s for %(usersgr)s' % dict(
622 'failed to edit permission %(repo)s for %(usersgr)s' % dict(
623 usersgr=group_name, repo=repo_name
623 usersgr=group_name, repo=repo_name
624 )
624 )
625 )
625 )
626
626
627 @HasPermissionAnyDecorator('hg.admin')
627 @HasPermissionAnyDecorator('hg.admin')
628 def revoke_users_group_permission(self, apiuser, repo_name, group_name):
628 def revoke_users_group_permission(self, apiuser, repo_name, group_name):
629 """
629 """
630 Revoke permission for users group on given repository
630 Revoke permission for users group on given repository
631
631
632 :param repo_name:
632 :param repo_name:
633 :param group_name:
633 :param group_name:
634 """
634 """
635
635
636 try:
636 try:
637 repo = Repository.get_by_repo_name(repo_name)
637 repo = Repository.get_by_repo_name(repo_name)
638 if repo is None:
638 if repo is None:
639 raise JSONRPCError('unknown repository %s' % repo)
639 raise JSONRPCError('unknown repository %s' % repo)
640
640
641 user_group = UsersGroup.get_by_group_name(group_name)
641 user_group = UsersGroup.get_by_group_name(group_name)
642 if user_group is None:
642 if user_group is None:
643 raise JSONRPCError('unknown users group %s' % user_group)
643 raise JSONRPCError('unknown users group %s' % user_group)
644
644
645 RepoModel().revoke_users_group_permission(repo=repo_name,
645 RepoModel().revoke_users_group_permission(repo=repo_name,
646 group_name=group_name)
646 group_name=group_name)
647
647
648 Session.commit()
648 Session.commit()
649 return dict(
649 return dict(
650 msg='Revoked perm for group: %s in repo: %s' % (
650 msg='Revoked perm for group: %s in repo: %s' % (
651 group_name, repo_name
651 group_name, repo_name
652 )
652 )
653 )
653 )
654 except Exception:
654 except Exception:
655 log.error(traceback.format_exc())
655 log.error(traceback.format_exc())
656 raise JSONRPCError(
656 raise JSONRPCError(
657 'failed to edit permission %(repo)s for %(usersgr)s' % dict(
657 'failed to edit permission %(repo)s for %(usersgr)s' % dict(
658 usersgr=group_name, repo=repo_name
658 usersgr=group_name, repo=repo_name
659 )
659 )
660 )
660 )
@@ -1,492 +1,495 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.repo
3 rhodecode.model.repo
4 ~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~
5
5
6 Repository model for rhodecode
6 Repository model for rhodecode
7
7
8 :created_on: Jun 5, 2010
8 :created_on: Jun 5, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 import os
25 import os
26 import shutil
26 import shutil
27 import logging
27 import logging
28 import traceback
28 import traceback
29 from datetime import datetime
29 from datetime import datetime
30
30
31 from rhodecode.lib.vcs.backends import get_backend
31 from rhodecode.lib.vcs.backends import get_backend
32
32
33 from rhodecode.lib import LazyProperty
33 from rhodecode.lib import LazyProperty
34 from rhodecode.lib import safe_str, safe_unicode
34 from rhodecode.lib import safe_str, safe_unicode
35 from rhodecode.lib.caching_query import FromCache
35 from rhodecode.lib.caching_query import FromCache
36 from rhodecode.lib.hooks import log_create_repository
36 from rhodecode.lib.hooks import log_create_repository
37
37
38 from rhodecode.model import BaseModel
38 from rhodecode.model import BaseModel
39 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
39 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
40 Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, RepoGroup
40 Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, RepoGroup
41
41
42
42
43 log = logging.getLogger(__name__)
43 log = logging.getLogger(__name__)
44
44
45
45
46 class RepoModel(BaseModel):
46 class RepoModel(BaseModel):
47
47
48 def __get_user(self, user):
48 def __get_user(self, user):
49 return self._get_instance(User, user, callback=User.get_by_username)
49 return self._get_instance(User, user, callback=User.get_by_username)
50
50
51 def __get_users_group(self, users_group):
51 def __get_users_group(self, users_group):
52 return self._get_instance(UsersGroup, users_group,
52 return self._get_instance(UsersGroup, users_group,
53 callback=UsersGroup.get_by_group_name)
53 callback=UsersGroup.get_by_group_name)
54
54
55 def __get_repos_group(self, repos_group):
55 def __get_repos_group(self, repos_group):
56 return self._get_instance(RepoGroup, repos_group,
56 return self._get_instance(RepoGroup, repos_group,
57 callback=RepoGroup.get_by_group_name)
57 callback=RepoGroup.get_by_group_name)
58
58
59 def __get_repo(self, repository):
59 def __get_repo(self, repository):
60 return self._get_instance(Repository, repository,
60 return self._get_instance(Repository, repository,
61 callback=Repository.get_by_repo_name)
61 callback=Repository.get_by_repo_name)
62
62
63 def __get_perm(self, permission):
63 def __get_perm(self, permission):
64 return self._get_instance(Permission, permission,
64 return self._get_instance(Permission, permission,
65 callback=Permission.get_by_key)
65 callback=Permission.get_by_key)
66
66
67 @LazyProperty
67 @LazyProperty
68 def repos_path(self):
68 def repos_path(self):
69 """
69 """
70 Get's the repositories root path from database
70 Get's the repositories root path from database
71 """
71 """
72
72
73 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
73 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
74 return q.ui_value
74 return q.ui_value
75
75
76 def get(self, repo_id, cache=False):
76 def get(self, repo_id, cache=False):
77 repo = self.sa.query(Repository)\
77 repo = self.sa.query(Repository)\
78 .filter(Repository.repo_id == repo_id)
78 .filter(Repository.repo_id == repo_id)
79
79
80 if cache:
80 if cache:
81 repo = repo.options(FromCache("sql_cache_short",
81 repo = repo.options(FromCache("sql_cache_short",
82 "get_repo_%s" % repo_id))
82 "get_repo_%s" % repo_id))
83 return repo.scalar()
83 return repo.scalar()
84
84
85 def get_repo(self, repository):
86 return self.__get_repo(repository)
87
85 def get_by_repo_name(self, repo_name, cache=False):
88 def get_by_repo_name(self, repo_name, cache=False):
86 repo = self.sa.query(Repository)\
89 repo = self.sa.query(Repository)\
87 .filter(Repository.repo_name == repo_name)
90 .filter(Repository.repo_name == repo_name)
88
91
89 if cache:
92 if cache:
90 repo = repo.options(FromCache("sql_cache_short",
93 repo = repo.options(FromCache("sql_cache_short",
91 "get_repo_%s" % repo_name))
94 "get_repo_%s" % repo_name))
92 return repo.scalar()
95 return repo.scalar()
93
96
94 def get_users_js(self):
97 def get_users_js(self):
95
98
96 users = self.sa.query(User).filter(User.active == True).all()
99 users = self.sa.query(User).filter(User.active == True).all()
97 u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
100 u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
98 users_array = '[%s]' % '\n'.join([u_tmpl % (u.user_id, u.name,
101 users_array = '[%s]' % '\n'.join([u_tmpl % (u.user_id, u.name,
99 u.lastname, u.username)
102 u.lastname, u.username)
100 for u in users])
103 for u in users])
101 return users_array
104 return users_array
102
105
103 def get_users_groups_js(self):
106 def get_users_groups_js(self):
104 users_groups = self.sa.query(UsersGroup)\
107 users_groups = self.sa.query(UsersGroup)\
105 .filter(UsersGroup.users_group_active == True).all()
108 .filter(UsersGroup.users_group_active == True).all()
106
109
107 g_tmpl = '''{id:%s, grname:"%s",grmembers:"%s"},'''
110 g_tmpl = '''{id:%s, grname:"%s",grmembers:"%s"},'''
108
111
109 users_groups_array = '[%s]' % '\n'.join([g_tmpl % \
112 users_groups_array = '[%s]' % '\n'.join([g_tmpl % \
110 (gr.users_group_id, gr.users_group_name,
113 (gr.users_group_id, gr.users_group_name,
111 len(gr.members))
114 len(gr.members))
112 for gr in users_groups])
115 for gr in users_groups])
113 return users_groups_array
116 return users_groups_array
114
117
115 def _get_defaults(self, repo_name):
118 def _get_defaults(self, repo_name):
116 """
119 """
117 Get's information about repository, and returns a dict for
120 Get's information about repository, and returns a dict for
118 usage in forms
121 usage in forms
119
122
120 :param repo_name:
123 :param repo_name:
121 """
124 """
122
125
123 repo_info = Repository.get_by_repo_name(repo_name)
126 repo_info = Repository.get_by_repo_name(repo_name)
124
127
125 if repo_info is None:
128 if repo_info is None:
126 return None
129 return None
127
130
128 defaults = repo_info.get_dict()
131 defaults = repo_info.get_dict()
129 group, repo_name = repo_info.groups_and_repo
132 group, repo_name = repo_info.groups_and_repo
130 defaults['repo_name'] = repo_name
133 defaults['repo_name'] = repo_name
131 defaults['repo_group'] = getattr(group[-1] if group else None,
134 defaults['repo_group'] = getattr(group[-1] if group else None,
132 'group_id', None)
135 'group_id', None)
133
136
134 # fill owner
137 # fill owner
135 if repo_info.user:
138 if repo_info.user:
136 defaults.update({'user': repo_info.user.username})
139 defaults.update({'user': repo_info.user.username})
137 else:
140 else:
138 replacement_user = User.query().filter(User.admin ==
141 replacement_user = User.query().filter(User.admin ==
139 True).first().username
142 True).first().username
140 defaults.update({'user': replacement_user})
143 defaults.update({'user': replacement_user})
141
144
142 # fill repository users
145 # fill repository users
143 for p in repo_info.repo_to_perm:
146 for p in repo_info.repo_to_perm:
144 defaults.update({'u_perm_%s' % p.user.username:
147 defaults.update({'u_perm_%s' % p.user.username:
145 p.permission.permission_name})
148 p.permission.permission_name})
146
149
147 # fill repository groups
150 # fill repository groups
148 for p in repo_info.users_group_to_perm:
151 for p in repo_info.users_group_to_perm:
149 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
152 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
150 p.permission.permission_name})
153 p.permission.permission_name})
151
154
152 return defaults
155 return defaults
153
156
154 def update(self, repo_name, form_data):
157 def update(self, repo_name, form_data):
155 try:
158 try:
156 cur_repo = self.get_by_repo_name(repo_name, cache=False)
159 cur_repo = self.get_by_repo_name(repo_name, cache=False)
157
160
158 # update permissions
161 # update permissions
159 for member, perm, member_type in form_data['perms_updates']:
162 for member, perm, member_type in form_data['perms_updates']:
160 if member_type == 'user':
163 if member_type == 'user':
161 # this updates existing one
164 # this updates existing one
162 RepoModel().grant_user_permission(
165 RepoModel().grant_user_permission(
163 repo=cur_repo, user=member, perm=perm
166 repo=cur_repo, user=member, perm=perm
164 )
167 )
165 else:
168 else:
166 RepoModel().grant_users_group_permission(
169 RepoModel().grant_users_group_permission(
167 repo=cur_repo, group_name=member, perm=perm
170 repo=cur_repo, group_name=member, perm=perm
168 )
171 )
169 # set new permissions
172 # set new permissions
170 for member, perm, member_type in form_data['perms_new']:
173 for member, perm, member_type in form_data['perms_new']:
171 if member_type == 'user':
174 if member_type == 'user':
172 RepoModel().grant_user_permission(
175 RepoModel().grant_user_permission(
173 repo=cur_repo, user=member, perm=perm
176 repo=cur_repo, user=member, perm=perm
174 )
177 )
175 else:
178 else:
176 RepoModel().grant_users_group_permission(
179 RepoModel().grant_users_group_permission(
177 repo=cur_repo, group_name=member, perm=perm
180 repo=cur_repo, group_name=member, perm=perm
178 )
181 )
179
182
180 # update current repo
183 # update current repo
181 for k, v in form_data.items():
184 for k, v in form_data.items():
182 if k == 'user':
185 if k == 'user':
183 cur_repo.user = User.get_by_username(v)
186 cur_repo.user = User.get_by_username(v)
184 elif k == 'repo_name':
187 elif k == 'repo_name':
185 pass
188 pass
186 elif k == 'repo_group':
189 elif k == 'repo_group':
187 cur_repo.group = RepoGroup.get(v)
190 cur_repo.group = RepoGroup.get(v)
188
191
189 else:
192 else:
190 setattr(cur_repo, k, v)
193 setattr(cur_repo, k, v)
191
194
192 new_name = cur_repo.get_new_name(form_data['repo_name'])
195 new_name = cur_repo.get_new_name(form_data['repo_name'])
193 cur_repo.repo_name = new_name
196 cur_repo.repo_name = new_name
194
197
195 self.sa.add(cur_repo)
198 self.sa.add(cur_repo)
196
199
197 if repo_name != new_name:
200 if repo_name != new_name:
198 # rename repository
201 # rename repository
199 self.__rename_repo(old=repo_name, new=new_name)
202 self.__rename_repo(old=repo_name, new=new_name)
200
203
201 return cur_repo
204 return cur_repo
202 except:
205 except:
203 log.error(traceback.format_exc())
206 log.error(traceback.format_exc())
204 raise
207 raise
205
208
206 def create(self, form_data, cur_user, just_db=False, fork=False):
209 def create(self, form_data, cur_user, just_db=False, fork=False):
207 from rhodecode.model.scm import ScmModel
210 from rhodecode.model.scm import ScmModel
208
211
209 try:
212 try:
210 if fork:
213 if fork:
211 fork_parent_id = form_data['fork_parent_id']
214 fork_parent_id = form_data['fork_parent_id']
212
215
213 # repo name is just a name of repository
216 # repo name is just a name of repository
214 # while repo_name_full is a full qualified name that is combined
217 # while repo_name_full is a full qualified name that is combined
215 # with name and path of group
218 # with name and path of group
216 repo_name = form_data['repo_name']
219 repo_name = form_data['repo_name']
217 repo_name_full = form_data['repo_name_full']
220 repo_name_full = form_data['repo_name_full']
218
221
219 new_repo = Repository()
222 new_repo = Repository()
220 new_repo.enable_statistics = False
223 new_repo.enable_statistics = False
221
224
222 for k, v in form_data.items():
225 for k, v in form_data.items():
223 if k == 'repo_name':
226 if k == 'repo_name':
224 v = repo_name_full
227 v = repo_name_full
225 if k == 'repo_group':
228 if k == 'repo_group':
226 k = 'group_id'
229 k = 'group_id'
227 if k == 'description':
230 if k == 'description':
228 v = v or repo_name
231 v = v or repo_name
229
232
230 setattr(new_repo, k, v)
233 setattr(new_repo, k, v)
231
234
232 if fork:
235 if fork:
233 parent_repo = Repository.get(fork_parent_id)
236 parent_repo = Repository.get(fork_parent_id)
234 new_repo.fork = parent_repo
237 new_repo.fork = parent_repo
235
238
236 new_repo.user_id = cur_user.user_id
239 new_repo.user_id = cur_user.user_id
237 self.sa.add(new_repo)
240 self.sa.add(new_repo)
238
241
239 def _create_default_perms():
242 def _create_default_perms():
240 # create default permission
243 # create default permission
241 repo_to_perm = UserRepoToPerm()
244 repo_to_perm = UserRepoToPerm()
242 default = 'repository.read'
245 default = 'repository.read'
243 for p in User.get_by_username('default').user_perms:
246 for p in User.get_by_username('default').user_perms:
244 if p.permission.permission_name.startswith('repository.'):
247 if p.permission.permission_name.startswith('repository.'):
245 default = p.permission.permission_name
248 default = p.permission.permission_name
246 break
249 break
247
250
248 default_perm = 'repository.none' if form_data['private'] else default
251 default_perm = 'repository.none' if form_data['private'] else default
249
252
250 repo_to_perm.permission_id = self.sa.query(Permission)\
253 repo_to_perm.permission_id = self.sa.query(Permission)\
251 .filter(Permission.permission_name == default_perm)\
254 .filter(Permission.permission_name == default_perm)\
252 .one().permission_id
255 .one().permission_id
253
256
254 repo_to_perm.repository = new_repo
257 repo_to_perm.repository = new_repo
255 repo_to_perm.user_id = User.get_by_username('default').user_id
258 repo_to_perm.user_id = User.get_by_username('default').user_id
256
259
257 self.sa.add(repo_to_perm)
260 self.sa.add(repo_to_perm)
258
261
259 if fork:
262 if fork:
260 if form_data.get('copy_permissions'):
263 if form_data.get('copy_permissions'):
261 repo = Repository.get(fork_parent_id)
264 repo = Repository.get(fork_parent_id)
262 user_perms = UserRepoToPerm.query()\
265 user_perms = UserRepoToPerm.query()\
263 .filter(UserRepoToPerm.repository == repo).all()
266 .filter(UserRepoToPerm.repository == repo).all()
264 group_perms = UsersGroupRepoToPerm.query()\
267 group_perms = UsersGroupRepoToPerm.query()\
265 .filter(UsersGroupRepoToPerm.repository == repo).all()
268 .filter(UsersGroupRepoToPerm.repository == repo).all()
266
269
267 for perm in user_perms:
270 for perm in user_perms:
268 UserRepoToPerm.create(perm.user, new_repo,
271 UserRepoToPerm.create(perm.user, new_repo,
269 perm.permission)
272 perm.permission)
270
273
271 for perm in group_perms:
274 for perm in group_perms:
272 UsersGroupRepoToPerm.create(perm.users_group, new_repo,
275 UsersGroupRepoToPerm.create(perm.users_group, new_repo,
273 perm.permission)
276 perm.permission)
274 else:
277 else:
275 _create_default_perms()
278 _create_default_perms()
276 else:
279 else:
277 _create_default_perms()
280 _create_default_perms()
278
281
279 if not just_db:
282 if not just_db:
280 self.__create_repo(repo_name, form_data['repo_type'],
283 self.__create_repo(repo_name, form_data['repo_type'],
281 form_data['repo_group'],
284 form_data['repo_group'],
282 form_data['clone_uri'])
285 form_data['clone_uri'])
283
286
284 # now automatically start following this repository as owner
287 # now automatically start following this repository as owner
285 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
288 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
286 cur_user.user_id)
289 cur_user.user_id)
287 log_create_repository(new_repo.get_dict(),
290 log_create_repository(new_repo.get_dict(),
288 created_by=cur_user.username)
291 created_by=cur_user.username)
289 return new_repo
292 return new_repo
290 except:
293 except:
291 log.error(traceback.format_exc())
294 log.error(traceback.format_exc())
292 raise
295 raise
293
296
294 def create_fork(self, form_data, cur_user):
297 def create_fork(self, form_data, cur_user):
295 """
298 """
296 Simple wrapper into executing celery task for fork creation
299 Simple wrapper into executing celery task for fork creation
297
300
298 :param form_data:
301 :param form_data:
299 :param cur_user:
302 :param cur_user:
300 """
303 """
301 from rhodecode.lib.celerylib import tasks, run_task
304 from rhodecode.lib.celerylib import tasks, run_task
302 run_task(tasks.create_repo_fork, form_data, cur_user)
305 run_task(tasks.create_repo_fork, form_data, cur_user)
303
306
304 def delete(self, repo):
307 def delete(self, repo):
305 repo = self.__get_repo(repo)
308 repo = self.__get_repo(repo)
306 try:
309 try:
307 self.sa.delete(repo)
310 self.sa.delete(repo)
308 self.__delete_repo(repo)
311 self.__delete_repo(repo)
309 except:
312 except:
310 log.error(traceback.format_exc())
313 log.error(traceback.format_exc())
311 raise
314 raise
312
315
313 def grant_user_permission(self, repo, user, perm):
316 def grant_user_permission(self, repo, user, perm):
314 """
317 """
315 Grant permission for user on given repository, or update existing one
318 Grant permission for user on given repository, or update existing one
316 if found
319 if found
317
320
318 :param repo: Instance of Repository, repository_id, or repository name
321 :param repo: Instance of Repository, repository_id, or repository name
319 :param user: Instance of User, user_id or username
322 :param user: Instance of User, user_id or username
320 :param perm: Instance of Permission, or permission_name
323 :param perm: Instance of Permission, or permission_name
321 """
324 """
322 user = self.__get_user(user)
325 user = self.__get_user(user)
323 repo = self.__get_repo(repo)
326 repo = self.__get_repo(repo)
324 permission = self.__get_perm(perm)
327 permission = self.__get_perm(perm)
325
328
326 # check if we have that permission already
329 # check if we have that permission already
327 obj = self.sa.query(UserRepoToPerm)\
330 obj = self.sa.query(UserRepoToPerm)\
328 .filter(UserRepoToPerm.user == user)\
331 .filter(UserRepoToPerm.user == user)\
329 .filter(UserRepoToPerm.repository == repo)\
332 .filter(UserRepoToPerm.repository == repo)\
330 .scalar()
333 .scalar()
331 if obj is None:
334 if obj is None:
332 # create new !
335 # create new !
333 obj = UserRepoToPerm()
336 obj = UserRepoToPerm()
334 obj.repository = repo
337 obj.repository = repo
335 obj.user = user
338 obj.user = user
336 obj.permission = permission
339 obj.permission = permission
337 self.sa.add(obj)
340 self.sa.add(obj)
338
341
339 def revoke_user_permission(self, repo, user):
342 def revoke_user_permission(self, repo, user):
340 """
343 """
341 Revoke permission for user on given repository
344 Revoke permission for user on given repository
342
345
343 :param repo: Instance of Repository, repository_id, or repository name
346 :param repo: Instance of Repository, repository_id, or repository name
344 :param user: Instance of User, user_id or username
347 :param user: Instance of User, user_id or username
345 """
348 """
346 user = self.__get_user(user)
349 user = self.__get_user(user)
347 repo = self.__get_repo(repo)
350 repo = self.__get_repo(repo)
348
351
349 obj = self.sa.query(UserRepoToPerm)\
352 obj = self.sa.query(UserRepoToPerm)\
350 .filter(UserRepoToPerm.repository == repo)\
353 .filter(UserRepoToPerm.repository == repo)\
351 .filter(UserRepoToPerm.user == user)\
354 .filter(UserRepoToPerm.user == user)\
352 .one()
355 .one()
353 self.sa.delete(obj)
356 self.sa.delete(obj)
354
357
355 def grant_users_group_permission(self, repo, group_name, perm):
358 def grant_users_group_permission(self, repo, group_name, perm):
356 """
359 """
357 Grant permission for users group on given repository, or update
360 Grant permission for users group on given repository, or update
358 existing one if found
361 existing one if found
359
362
360 :param repo: Instance of Repository, repository_id, or repository name
363 :param repo: Instance of Repository, repository_id, or repository name
361 :param group_name: Instance of UserGroup, users_group_id,
364 :param group_name: Instance of UserGroup, users_group_id,
362 or users group name
365 or users group name
363 :param perm: Instance of Permission, or permission_name
366 :param perm: Instance of Permission, or permission_name
364 """
367 """
365 repo = self.__get_repo(repo)
368 repo = self.__get_repo(repo)
366 group_name = self.__get_users_group(group_name)
369 group_name = self.__get_users_group(group_name)
367 permission = self.__get_perm(perm)
370 permission = self.__get_perm(perm)
368
371
369 # check if we have that permission already
372 # check if we have that permission already
370 obj = self.sa.query(UsersGroupRepoToPerm)\
373 obj = self.sa.query(UsersGroupRepoToPerm)\
371 .filter(UsersGroupRepoToPerm.users_group == group_name)\
374 .filter(UsersGroupRepoToPerm.users_group == group_name)\
372 .filter(UsersGroupRepoToPerm.repository == repo)\
375 .filter(UsersGroupRepoToPerm.repository == repo)\
373 .scalar()
376 .scalar()
374
377
375 if obj is None:
378 if obj is None:
376 # create new
379 # create new
377 obj = UsersGroupRepoToPerm()
380 obj = UsersGroupRepoToPerm()
378
381
379 obj.repository = repo
382 obj.repository = repo
380 obj.users_group = group_name
383 obj.users_group = group_name
381 obj.permission = permission
384 obj.permission = permission
382 self.sa.add(obj)
385 self.sa.add(obj)
383
386
384 def revoke_users_group_permission(self, repo, group_name):
387 def revoke_users_group_permission(self, repo, group_name):
385 """
388 """
386 Revoke permission for users group on given repository
389 Revoke permission for users group on given repository
387
390
388 :param repo: Instance of Repository, repository_id, or repository name
391 :param repo: Instance of Repository, repository_id, or repository name
389 :param group_name: Instance of UserGroup, users_group_id,
392 :param group_name: Instance of UserGroup, users_group_id,
390 or users group name
393 or users group name
391 """
394 """
392 repo = self.__get_repo(repo)
395 repo = self.__get_repo(repo)
393 group_name = self.__get_users_group(group_name)
396 group_name = self.__get_users_group(group_name)
394
397
395 obj = self.sa.query(UsersGroupRepoToPerm)\
398 obj = self.sa.query(UsersGroupRepoToPerm)\
396 .filter(UsersGroupRepoToPerm.repository == repo)\
399 .filter(UsersGroupRepoToPerm.repository == repo)\
397 .filter(UsersGroupRepoToPerm.users_group == group_name)\
400 .filter(UsersGroupRepoToPerm.users_group == group_name)\
398 .one()
401 .one()
399 self.sa.delete(obj)
402 self.sa.delete(obj)
400
403
401 def delete_stats(self, repo_name):
404 def delete_stats(self, repo_name):
402 """
405 """
403 removes stats for given repo
406 removes stats for given repo
404
407
405 :param repo_name:
408 :param repo_name:
406 """
409 """
407 try:
410 try:
408 obj = self.sa.query(Statistics)\
411 obj = self.sa.query(Statistics)\
409 .filter(Statistics.repository ==
412 .filter(Statistics.repository ==
410 self.get_by_repo_name(repo_name))\
413 self.get_by_repo_name(repo_name))\
411 .one()
414 .one()
412 self.sa.delete(obj)
415 self.sa.delete(obj)
413 except:
416 except:
414 log.error(traceback.format_exc())
417 log.error(traceback.format_exc())
415 raise
418 raise
416
419
417 def __create_repo(self, repo_name, alias, new_parent_id, clone_uri=False):
420 def __create_repo(self, repo_name, alias, new_parent_id, clone_uri=False):
418 """
421 """
419 makes repository on filesystem. It's group aware means it'll create
422 makes repository on filesystem. It's group aware means it'll create
420 a repository within a group, and alter the paths accordingly of
423 a repository within a group, and alter the paths accordingly of
421 group location
424 group location
422
425
423 :param repo_name:
426 :param repo_name:
424 :param alias:
427 :param alias:
425 :param parent_id:
428 :param parent_id:
426 :param clone_uri:
429 :param clone_uri:
427 """
430 """
428 from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
431 from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
429
432
430 if new_parent_id:
433 if new_parent_id:
431 paths = RepoGroup.get(new_parent_id)\
434 paths = RepoGroup.get(new_parent_id)\
432 .full_path.split(RepoGroup.url_sep())
435 .full_path.split(RepoGroup.url_sep())
433 new_parent_path = os.sep.join(paths)
436 new_parent_path = os.sep.join(paths)
434 else:
437 else:
435 new_parent_path = ''
438 new_parent_path = ''
436
439
437 # we need to make it str for mercurial
440 # we need to make it str for mercurial
438 repo_path = os.path.join(*map(lambda x: safe_str(x),
441 repo_path = os.path.join(*map(lambda x: safe_str(x),
439 [self.repos_path, new_parent_path, repo_name]))
442 [self.repos_path, new_parent_path, repo_name]))
440
443
441 # check if this path is not a repository
444 # check if this path is not a repository
442 if is_valid_repo(repo_path, self.repos_path):
445 if is_valid_repo(repo_path, self.repos_path):
443 raise Exception('This path %s is a valid repository' % repo_path)
446 raise Exception('This path %s is a valid repository' % repo_path)
444
447
445 # check if this path is a group
448 # check if this path is a group
446 if is_valid_repos_group(repo_path, self.repos_path):
449 if is_valid_repos_group(repo_path, self.repos_path):
447 raise Exception('This path %s is a valid group' % repo_path)
450 raise Exception('This path %s is a valid group' % repo_path)
448
451
449 log.info('creating repo %s in %s @ %s' % (
452 log.info('creating repo %s in %s @ %s' % (
450 repo_name, safe_unicode(repo_path), clone_uri
453 repo_name, safe_unicode(repo_path), clone_uri
451 )
454 )
452 )
455 )
453 backend = get_backend(alias)
456 backend = get_backend(alias)
454
457
455 backend(repo_path, create=True, src_url=clone_uri)
458 backend(repo_path, create=True, src_url=clone_uri)
456
459
457 def __rename_repo(self, old, new):
460 def __rename_repo(self, old, new):
458 """
461 """
459 renames repository on filesystem
462 renames repository on filesystem
460
463
461 :param old: old name
464 :param old: old name
462 :param new: new name
465 :param new: new name
463 """
466 """
464 log.info('renaming repo from %s to %s' % (old, new))
467 log.info('renaming repo from %s to %s' % (old, new))
465
468
466 old_path = os.path.join(self.repos_path, old)
469 old_path = os.path.join(self.repos_path, old)
467 new_path = os.path.join(self.repos_path, new)
470 new_path = os.path.join(self.repos_path, new)
468 if os.path.isdir(new_path):
471 if os.path.isdir(new_path):
469 raise Exception(
472 raise Exception(
470 'Was trying to rename to already existing dir %s' % new_path
473 'Was trying to rename to already existing dir %s' % new_path
471 )
474 )
472 shutil.move(old_path, new_path)
475 shutil.move(old_path, new_path)
473
476
474 def __delete_repo(self, repo):
477 def __delete_repo(self, repo):
475 """
478 """
476 removes repo from filesystem, the removal is acctually made by
479 removes repo from filesystem, the removal is acctually made by
477 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
480 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
478 repository is no longer valid for rhodecode, can be undeleted later on
481 repository is no longer valid for rhodecode, can be undeleted later on
479 by reverting the renames on this repository
482 by reverting the renames on this repository
480
483
481 :param repo: repo object
484 :param repo: repo object
482 """
485 """
483 rm_path = os.path.join(self.repos_path, repo.repo_name)
486 rm_path = os.path.join(self.repos_path, repo.repo_name)
484 log.info("Removing %s" % (rm_path))
487 log.info("Removing %s" % (rm_path))
485 # disable hg/git
488 # disable hg/git
486 alias = repo.repo_type
489 alias = repo.repo_type
487 shutil.move(os.path.join(rm_path, '.%s' % alias),
490 shutil.move(os.path.join(rm_path, '.%s' % alias),
488 os.path.join(rm_path, 'rm__.%s' % alias))
491 os.path.join(rm_path, 'rm__.%s' % alias))
489 # disable repo
492 # disable repo
490 _d = 'rm__%s__%s' % (datetime.now().strftime('%Y%m%d_%H%M%S_%f'),
493 _d = 'rm__%s__%s' % (datetime.now().strftime('%Y%m%d_%H%M%S_%f'),
491 repo.repo_name)
494 repo.repo_name)
492 shutil.move(rm_path, os.path.join(self.repos_path, _d))
495 shutil.move(rm_path, os.path.join(self.repos_path, _d))
General Comments 0
You need to be logged in to leave comments. Login now