##// END OF EJS Templates
added API call for locking/unlocking repositories
marcink -
r2737:e21cb7b1 beta
parent child Browse files
Show More
@@ -1,850 +1,876 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 to RhodeCode is
10 with JSON protocol both ways. An url to send API request to 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>, # matching id sent by request
53 "id":<id>, # matching id sent by request
54 "result": "<result>"|null, # JSON formatted result, null if any errors
54 "result": "<result>"|null, # JSON formatted result, null if any errors
55 "error": "null"|<error_message> # JSON formatted error (if any)
55 "error": "null"|<error_message> # JSON formatted error (if any)
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
62
63 API CLIENT
63 API CLIENT
64 ++++++++++
64 ++++++++++
65
65
66 From version 1.4 RhodeCode adds a script that allows to easily
66 From version 1.4 RhodeCode adds a script that allows to easily
67 communicate with API. After installing RhodeCode a `rhodecode-api` script
67 communicate with API. After installing RhodeCode a `rhodecode-api` script
68 will be available.
68 will be available.
69
69
70 To get started quickly simply run::
70 To get started quickly simply run::
71
71
72 rhodecode-api _create_config --apikey=<youapikey> --apihost=<rhodecode host>
72 rhodecode-api _create_config --apikey=<youapikey> --apihost=<rhodecode host>
73
73
74 This will create a file named .config in the directory you executed it storing
74 This will create a file named .config in the directory you executed it storing
75 json config file with credentials. You can skip this step and always provide
75 json config file with credentials. You can skip this step and always provide
76 both of the arguments to be able to communicate with server
76 both of the arguments to be able to communicate with server
77
77
78
78
79 after that simply run any api command for example get_repo::
79 after that simply run any api command for example get_repo::
80
80
81 rhodecode-api get_repo
81 rhodecode-api get_repo
82
82
83 calling {"api_key": "<apikey>", "id": 75, "args": {}, "method": "get_repo"} to http://127.0.0.1:5000
83 calling {"api_key": "<apikey>", "id": 75, "args": {}, "method": "get_repo"} to http://127.0.0.1:5000
84 rhodecode said:
84 rhodecode said:
85 {'error': 'Missing non optional `repoid` arg in JSON DATA',
85 {'error': 'Missing non optional `repoid` arg in JSON DATA',
86 'id': 75,
86 'id': 75,
87 'result': None}
87 'result': None}
88
88
89 Ups looks like we forgot to add an argument
89 Ups looks like we forgot to add an argument
90
90
91 Let's try again now giving the repoid as parameters::
91 Let's try again now giving the repoid as parameters::
92
92
93 rhodecode-api get_repo repoid:rhodecode
93 rhodecode-api get_repo repoid:rhodecode
94
94
95 calling {"api_key": "<apikey>", "id": 39, "args": {"repoid": "rhodecode"}, "method": "get_repo"} to http://127.0.0.1:5000
95 calling {"api_key": "<apikey>", "id": 39, "args": {"repoid": "rhodecode"}, "method": "get_repo"} to http://127.0.0.1:5000
96 rhodecode said:
96 rhodecode said:
97 {'error': None,
97 {'error': None,
98 'id': 39,
98 'id': 39,
99 'result': <json data...>}
99 'result': <json data...>}
100
100
101
101
102
102
103 API METHODS
103 API METHODS
104 +++++++++++
104 +++++++++++
105
105
106
106
107 pull
107 pull
108 ----
108 ----
109
109
110 Pulls given repo from remote location. Can be used to automatically keep
110 Pulls given repo from remote location. Can be used to automatically keep
111 remote repos up to date. This command can be executed only using api_key
111 remote repos up to date. This command can be executed only using api_key
112 belonging to user with admin rights
112 belonging to user with admin rights
113
113
114 INPUT::
114 INPUT::
115
115
116 id : <id_for_response>
116 id : <id_for_response>
117 api_key : "<api_key>"
117 api_key : "<api_key>"
118 method : "pull"
118 method : "pull"
119 args : {
119 args : {
120 "repoid" : "<reponame or repo_id>"
120 "repoid" : "<reponame or repo_id>"
121 }
121 }
122
122
123 OUTPUT::
123 OUTPUT::
124
124
125 id : <id_given_in_input>
125 id : <id_given_in_input>
126 result : "Pulled from `<reponame>`"
126 result : "Pulled from `<reponame>`"
127 error : null
127 error : null
128
128
129
129
130 rescan_repos
130 rescan_repos
131 ------------
131 ------------
132
132
133 Dispatch rescan repositories action. If remove_obsolete is set
133 Dispatch rescan repositories action. If remove_obsolete is set
134 RhodeCode will delete repos that are in database but not in the filesystem.
134 RhodeCode will delete repos that are in database but not in the filesystem.
135 This command can be executed only using api_key belonging to user with admin
135 This command can be executed only using api_key belonging to user with admin
136 rights.
136 rights.
137
137
138 INPUT::
138 INPUT::
139
139
140 id : <id_for_response>
140 id : <id_for_response>
141 api_key : "<api_key>"
141 api_key : "<api_key>"
142 method : "rescan_repos"
142 method : "rescan_repos"
143 args : {
143 args : {
144 "remove_obsolete" : "<boolean = Optional(False)>"
144 "remove_obsolete" : "<boolean = Optional(False)>"
145 }
145 }
146
146
147 OUTPUT::
147 OUTPUT::
148
148
149 id : <id_given_in_input>
149 id : <id_given_in_input>
150 result : "{'added': [<list of names of added repos>],
150 result : "{'added': [<list of names of added repos>],
151 'removed': [<list of names of removed repos>]}"
151 'removed': [<list of names of removed repos>]}"
152 error : null
152 error : null
153
153
154
154
155 lock
156 ----
157
158 Set locking state on given repository by given user.
159 This command can be executed only using api_key belonging to user with admin
160 rights.
161
162 INPUT::
163
164 id : <id_for_response>
165 api_key : "<api_key>"
166 method : "lock"
167 args : {
168 "repoid" : "<reponame or repo_id>"
169 "userid" : "<user_id or username>",
170 "locked" : "<bool true|false>"
171
172 }
173
174 OUTPUT::
175
176 id : <id_given_in_input>
177 result : "User `<username>` set lock state for repo `<reponame>` to `true|false`"
178 error : null
179
180
155 get_user
181 get_user
156 --------
182 --------
157
183
158 Get's an user by username or user_id, Returns empty result if user is not found.
184 Get's an user by username or user_id, Returns empty result if user is not found.
159 This command can be executed only using api_key belonging to user with admin
185 This command can be executed only using api_key belonging to user with admin
160 rights.
186 rights.
161
187
162
188
163 INPUT::
189 INPUT::
164
190
165 id : <id_for_response>
191 id : <id_for_response>
166 api_key : "<api_key>"
192 api_key : "<api_key>"
167 method : "get_user"
193 method : "get_user"
168 args : {
194 args : {
169 "userid" : "<username or user_id>"
195 "userid" : "<username or user_id>"
170 }
196 }
171
197
172 OUTPUT::
198 OUTPUT::
173
199
174 id : <id_given_in_input>
200 id : <id_given_in_input>
175 result: None if user does not exist or
201 result: None if user does not exist or
176 {
202 {
177 "user_id" : "<user_id>",
203 "user_id" : "<user_id>",
178 "username" : "<username>",
204 "username" : "<username>",
179 "firstname": "<firstname>",
205 "firstname": "<firstname>",
180 "lastname" : "<lastname>",
206 "lastname" : "<lastname>",
181 "email" : "<email>",
207 "email" : "<email>",
182 "emails": "<list_of_all_additional_emails>",
208 "emails": "<list_of_all_additional_emails>",
183 "active" : "<bool>",
209 "active" : "<bool>",
184 "admin" :Β  "<bool>",
210 "admin" :Β  "<bool>",
185 "ldap_dn" : "<ldap_dn>",
211 "ldap_dn" : "<ldap_dn>",
186 "last_login": "<last_login>",
212 "last_login": "<last_login>",
187 "permissions": {
213 "permissions": {
188 "global": ["hg.create.repository",
214 "global": ["hg.create.repository",
189 "repository.read",
215 "repository.read",
190 "hg.register.manual_activate"],
216 "hg.register.manual_activate"],
191 "repositories": {"repo1": "repository.none"},
217 "repositories": {"repo1": "repository.none"},
192 "repositories_groups": {"Group1": "group.read"}
218 "repositories_groups": {"Group1": "group.read"}
193 },
219 },
194 }
220 }
195
221
196 error: null
222 error: null
197
223
198
224
199 get_users
225 get_users
200 ---------
226 ---------
201
227
202 Lists all existing users. This command can be executed only using api_key
228 Lists all existing users. This command can be executed only using api_key
203 belonging to user with admin rights.
229 belonging to user with admin rights.
204
230
205
231
206 INPUT::
232 INPUT::
207
233
208 id : <id_for_response>
234 id : <id_for_response>
209 api_key : "<api_key>"
235 api_key : "<api_key>"
210 method : "get_users"
236 method : "get_users"
211 args : { }
237 args : { }
212
238
213 OUTPUT::
239 OUTPUT::
214
240
215 id : <id_given_in_input>
241 id : <id_given_in_input>
216 result: [
242 result: [
217 {
243 {
218 "user_id" : "<user_id>",
244 "user_id" : "<user_id>",
219 "username" : "<username>",
245 "username" : "<username>",
220 "firstname": "<firstname>",
246 "firstname": "<firstname>",
221 "lastname" : "<lastname>",
247 "lastname" : "<lastname>",
222 "email" : "<email>",
248 "email" : "<email>",
223 "emails": "<list_of_all_additional_emails>",
249 "emails": "<list_of_all_additional_emails>",
224 "active" : "<bool>",
250 "active" : "<bool>",
225 "admin" :Β  "<bool>",
251 "admin" :Β  "<bool>",
226 "ldap_dn" : "<ldap_dn>",
252 "ldap_dn" : "<ldap_dn>",
227 "last_login": "<last_login>",
253 "last_login": "<last_login>",
228 },
254 },
229 …
255 …
230 ]
256 ]
231 error: null
257 error: null
232
258
233
259
234 create_user
260 create_user
235 -----------
261 -----------
236
262
237 Creates new user. This command can
263 Creates new user. This command can
238 be executed only using api_key belonging to user with admin rights.
264 be executed only using api_key belonging to user with admin rights.
239
265
240
266
241 INPUT::
267 INPUT::
242
268
243 id : <id_for_response>
269 id : <id_for_response>
244 api_key : "<api_key>"
270 api_key : "<api_key>"
245 method : "create_user"
271 method : "create_user"
246 args : {
272 args : {
247 "username" : "<username>",
273 "username" : "<username>",
248 "email" : "<useremail>",
274 "email" : "<useremail>",
249 "password" : "<password>",
275 "password" : "<password>",
250 "firstname" : "<firstname> = Optional(None)",
276 "firstname" : "<firstname> = Optional(None)",
251 "lastname" : "<lastname> = Optional(None)",
277 "lastname" : "<lastname> = Optional(None)",
252 "active" : "<bool> = Optional(True)",
278 "active" : "<bool> = Optional(True)",
253 "admin" : "<bool> = Optional(False)",
279 "admin" : "<bool> = Optional(False)",
254 "ldap_dn" : "<ldap_dn> = Optional(None)"
280 "ldap_dn" : "<ldap_dn> = Optional(None)"
255 }
281 }
256
282
257 OUTPUT::
283 OUTPUT::
258
284
259 id : <id_given_in_input>
285 id : <id_given_in_input>
260 result: {
286 result: {
261 "msg" : "created new user `<username>`",
287 "msg" : "created new user `<username>`",
262 "user": {
288 "user": {
263 "user_id" : "<user_id>",
289 "user_id" : "<user_id>",
264 "username" : "<username>",
290 "username" : "<username>",
265 "firstname": "<firstname>",
291 "firstname": "<firstname>",
266 "lastname" : "<lastname>",
292 "lastname" : "<lastname>",
267 "email" : "<email>",
293 "email" : "<email>",
268 "emails": "<list_of_all_additional_emails>",
294 "emails": "<list_of_all_additional_emails>",
269 "active" : "<bool>",
295 "active" : "<bool>",
270 "admin" :Β  "<bool>",
296 "admin" :Β  "<bool>",
271 "ldap_dn" : "<ldap_dn>",
297 "ldap_dn" : "<ldap_dn>",
272 "last_login": "<last_login>",
298 "last_login": "<last_login>",
273 },
299 },
274 }
300 }
275 error: null
301 error: null
276
302
277
303
278 update_user
304 update_user
279 -----------
305 -----------
280
306
281 updates given user if such user exists. This command can
307 updates given user if such user exists. This command can
282 be executed only using api_key belonging to user with admin rights.
308 be executed only using api_key belonging to user with admin rights.
283
309
284
310
285 INPUT::
311 INPUT::
286
312
287 id : <id_for_response>
313 id : <id_for_response>
288 api_key : "<api_key>"
314 api_key : "<api_key>"
289 method : "update_user"
315 method : "update_user"
290 args : {
316 args : {
291 "userid" : "<user_id or username>",
317 "userid" : "<user_id or username>",
292 "username" : "<username> = Optional",
318 "username" : "<username> = Optional",
293 "email" : "<useremail> = Optional",
319 "email" : "<useremail> = Optional",
294 "password" : "<password> = Optional",
320 "password" : "<password> = Optional",
295 "firstname" : "<firstname> = Optional",
321 "firstname" : "<firstname> = Optional",
296 "lastname" : "<lastname> = Optional",
322 "lastname" : "<lastname> = Optional",
297 "active" : "<bool> = Optional",
323 "active" : "<bool> = Optional",
298 "admin" : "<bool> = Optional",
324 "admin" : "<bool> = Optional",
299 "ldap_dn" : "<ldap_dn> = Optional"
325 "ldap_dn" : "<ldap_dn> = Optional"
300 }
326 }
301
327
302 OUTPUT::
328 OUTPUT::
303
329
304 id : <id_given_in_input>
330 id : <id_given_in_input>
305 result: {
331 result: {
306 "msg" : "updated user ID:<userid> <username>",
332 "msg" : "updated user ID:<userid> <username>",
307 "user": {
333 "user": {
308 "user_id" : "<user_id>",
334 "user_id" : "<user_id>",
309 "username" : "<username>",
335 "username" : "<username>",
310 "firstname": "<firstname>",
336 "firstname": "<firstname>",
311 "lastname" : "<lastname>",
337 "lastname" : "<lastname>",
312 "email" : "<email>",
338 "email" : "<email>",
313 "emails": "<list_of_all_additional_emails>",
339 "emails": "<list_of_all_additional_emails>",
314 "active" : "<bool>",
340 "active" : "<bool>",
315 "admin" :Β  "<bool>",
341 "admin" :Β  "<bool>",
316 "ldap_dn" : "<ldap_dn>",
342 "ldap_dn" : "<ldap_dn>",
317 "last_login": "<last_login>",
343 "last_login": "<last_login>",
318 },
344 },
319 }
345 }
320 error: null
346 error: null
321
347
322
348
323 delete_user
349 delete_user
324 -----------
350 -----------
325
351
326
352
327 deletes givenuser if such user exists. This command can
353 deletes givenuser if such user exists. This command can
328 be executed only using api_key belonging to user with admin rights.
354 be executed only using api_key belonging to user with admin rights.
329
355
330
356
331 INPUT::
357 INPUT::
332
358
333 id : <id_for_response>
359 id : <id_for_response>
334 api_key : "<api_key>"
360 api_key : "<api_key>"
335 method : "delete_user"
361 method : "delete_user"
336 args : {
362 args : {
337 "userid" : "<user_id or username>",
363 "userid" : "<user_id or username>",
338 }
364 }
339
365
340 OUTPUT::
366 OUTPUT::
341
367
342 id : <id_given_in_input>
368 id : <id_given_in_input>
343 result: {
369 result: {
344 "msg" : "deleted user ID:<userid> <username>",
370 "msg" : "deleted user ID:<userid> <username>",
345 "user": null
371 "user": null
346 }
372 }
347 error: null
373 error: null
348
374
349
375
350 get_users_group
376 get_users_group
351 ---------------
377 ---------------
352
378
353 Gets an existing users group. This command can be executed only using api_key
379 Gets an existing users group. This command can be executed only using api_key
354 belonging to user with admin rights.
380 belonging to user with admin rights.
355
381
356
382
357 INPUT::
383 INPUT::
358
384
359 id : <id_for_response>
385 id : <id_for_response>
360 api_key : "<api_key>"
386 api_key : "<api_key>"
361 method : "get_users_group"
387 method : "get_users_group"
362 args : {
388 args : {
363 "usersgroupid" : "<users group id or name>"
389 "usersgroupid" : "<users group id or name>"
364 }
390 }
365
391
366 OUTPUT::
392 OUTPUT::
367
393
368 id : <id_given_in_input>
394 id : <id_given_in_input>
369 result : None if group not exist
395 result : None if group not exist
370 {
396 {
371 "users_group_id" : "<id>",
397 "users_group_id" : "<id>",
372 "group_name" : "<groupname>",
398 "group_name" : "<groupname>",
373 "active": "<bool>",
399 "active": "<bool>",
374 "members" : [
400 "members" : [
375 {
401 {
376 "user_id" : "<user_id>",
402 "user_id" : "<user_id>",
377 "username" : "<username>",
403 "username" : "<username>",
378 "firstname": "<firstname>",
404 "firstname": "<firstname>",
379 "lastname" : "<lastname>",
405 "lastname" : "<lastname>",
380 "email" : "<email>",
406 "email" : "<email>",
381 "emails": "<list_of_all_additional_emails>",
407 "emails": "<list_of_all_additional_emails>",
382 "active" : "<bool>",
408 "active" : "<bool>",
383 "admin" :Β  "<bool>",
409 "admin" :Β  "<bool>",
384 "ldap_dn" : "<ldap_dn>",
410 "ldap_dn" : "<ldap_dn>",
385 "last_login": "<last_login>",
411 "last_login": "<last_login>",
386 },
412 },
387 …
413 …
388 ]
414 ]
389 }
415 }
390 error : null
416 error : null
391
417
392
418
393 get_users_groups
419 get_users_groups
394 ----------------
420 ----------------
395
421
396 Lists all existing users groups. This command can be executed only using
422 Lists all existing users groups. This command can be executed only using
397 api_key belonging to user with admin rights.
423 api_key belonging to user with admin rights.
398
424
399
425
400 INPUT::
426 INPUT::
401
427
402 id : <id_for_response>
428 id : <id_for_response>
403 api_key : "<api_key>"
429 api_key : "<api_key>"
404 method : "get_users_groups"
430 method : "get_users_groups"
405 args : { }
431 args : { }
406
432
407 OUTPUT::
433 OUTPUT::
408
434
409 id : <id_given_in_input>
435 id : <id_given_in_input>
410 result : [
436 result : [
411 {
437 {
412 "users_group_id" : "<id>",
438 "users_group_id" : "<id>",
413 "group_name" : "<groupname>",
439 "group_name" : "<groupname>",
414 "active": "<bool>",
440 "active": "<bool>",
415 "members" : [
441 "members" : [
416 {
442 {
417 "user_id" : "<user_id>",
443 "user_id" : "<user_id>",
418 "username" : "<username>",
444 "username" : "<username>",
419 "firstname": "<firstname>",
445 "firstname": "<firstname>",
420 "lastname" : "<lastname>",
446 "lastname" : "<lastname>",
421 "email" : "<email>",
447 "email" : "<email>",
422 "emails": "<list_of_all_additional_emails>",
448 "emails": "<list_of_all_additional_emails>",
423 "active" : "<bool>",
449 "active" : "<bool>",
424 "admin" :Β  "<bool>",
450 "admin" :Β  "<bool>",
425 "ldap_dn" : "<ldap_dn>",
451 "ldap_dn" : "<ldap_dn>",
426 "last_login": "<last_login>",
452 "last_login": "<last_login>",
427 },
453 },
428 …
454 …
429 ]
455 ]
430 },
456 },
431 …
457 …
432 ]
458 ]
433 error : null
459 error : null
434
460
435
461
436 create_users_group
462 create_users_group
437 ------------------
463 ------------------
438
464
439 Creates new users group. This command can be executed only using api_key
465 Creates new users group. This command can be executed only using api_key
440 belonging to user with admin rights
466 belonging to user with admin rights
441
467
442
468
443 INPUT::
469 INPUT::
444
470
445 id : <id_for_response>
471 id : <id_for_response>
446 api_key : "<api_key>"
472 api_key : "<api_key>"
447 method : "create_users_group"
473 method : "create_users_group"
448 args: {
474 args: {
449 "group_name": "<groupname>",
475 "group_name": "<groupname>",
450 "active":"<bool> = Optional(True)"
476 "active":"<bool> = Optional(True)"
451 }
477 }
452
478
453 OUTPUT::
479 OUTPUT::
454
480
455 id : <id_given_in_input>
481 id : <id_given_in_input>
456 result: {
482 result: {
457 "msg": "created new users group `<groupname>`",
483 "msg": "created new users group `<groupname>`",
458 "users_group": {
484 "users_group": {
459 "users_group_id" : "<id>",
485 "users_group_id" : "<id>",
460 "group_name" : "<groupname>",
486 "group_name" : "<groupname>",
461 "active": "<bool>",
487 "active": "<bool>",
462 "members" : [
488 "members" : [
463 {
489 {
464 "user_id" : "<user_id>",
490 "user_id" : "<user_id>",
465 "username" : "<username>",
491 "username" : "<username>",
466 "firstname": "<firstname>",
492 "firstname": "<firstname>",
467 "lastname" : "<lastname>",
493 "lastname" : "<lastname>",
468 "email" : "<email>",
494 "email" : "<email>",
469 "emails": "<list_of_all_additional_emails>",
495 "emails": "<list_of_all_additional_emails>",
470 "active" : "<bool>",
496 "active" : "<bool>",
471 "admin" :Β  "<bool>",
497 "admin" :Β  "<bool>",
472 "ldap_dn" : "<ldap_dn>",
498 "ldap_dn" : "<ldap_dn>",
473 "last_login": "<last_login>",
499 "last_login": "<last_login>",
474 },
500 },
475 …
501 …
476 ]
502 ]
477 },
503 },
478 }
504 }
479 error: null
505 error: null
480
506
481
507
482 add_user_to_users_group
508 add_user_to_users_group
483 -----------------------
509 -----------------------
484
510
485 Adds a user to a users group. If user exists in that group success will be
511 Adds a user to a users group. If user exists in that group success will be
486 `false`. This command can be executed only using api_key
512 `false`. This command can be executed only using api_key
487 belonging to user with admin rights
513 belonging to user with admin rights
488
514
489
515
490 INPUT::
516 INPUT::
491
517
492 id : <id_for_response>
518 id : <id_for_response>
493 api_key : "<api_key>"
519 api_key : "<api_key>"
494 method : "add_user_users_group"
520 method : "add_user_users_group"
495 args: {
521 args: {
496 "usersgroupid" : "<users group id or name>",
522 "usersgroupid" : "<users group id or name>",
497 "userid" : "<user_id or username>",
523 "userid" : "<user_id or username>",
498 }
524 }
499
525
500 OUTPUT::
526 OUTPUT::
501
527
502 id : <id_given_in_input>
528 id : <id_given_in_input>
503 result: {
529 result: {
504 "success": True|False # depends on if member is in group
530 "success": True|False # depends on if member is in group
505 "msg": "added member `<username>` to users group `<groupname>` |
531 "msg": "added member `<username>` to users group `<groupname>` |
506 User is already in that group"
532 User is already in that group"
507 }
533 }
508 error: null
534 error: null
509
535
510
536
511 remove_user_from_users_group
537 remove_user_from_users_group
512 ----------------------------
538 ----------------------------
513
539
514 Removes a user from a users group. If user is not in given group success will
540 Removes a user from a users group. If user is not in given group success will
515 be `false`. This command can be executed only
541 be `false`. This command can be executed only
516 using api_key belonging to user with admin rights
542 using api_key belonging to user with admin rights
517
543
518
544
519 INPUT::
545 INPUT::
520
546
521 id : <id_for_response>
547 id : <id_for_response>
522 api_key : "<api_key>"
548 api_key : "<api_key>"
523 method : "remove_user_from_users_group"
549 method : "remove_user_from_users_group"
524 args: {
550 args: {
525 "usersgroupid" : "<users group id or name>",
551 "usersgroupid" : "<users group id or name>",
526 "userid" : "<user_id or username>",
552 "userid" : "<user_id or username>",
527 }
553 }
528
554
529 OUTPUT::
555 OUTPUT::
530
556
531 id : <id_given_in_input>
557 id : <id_given_in_input>
532 result: {
558 result: {
533 "success": True|False, # depends on if member is in group
559 "success": True|False, # depends on if member is in group
534 "msg": "removed member <username> from users group <groupname> |
560 "msg": "removed member <username> from users group <groupname> |
535 User wasn't in group"
561 User wasn't in group"
536 }
562 }
537 error: null
563 error: null
538
564
539
565
540 get_repo
566 get_repo
541 --------
567 --------
542
568
543 Gets an existing repository by it's name or repository_id. Members will return
569 Gets an existing repository by it's name or repository_id. Members will return
544 either users_group or user associated to that repository. This command can
570 either users_group or user associated to that repository. This command can
545 be executed only using api_key belonging to user with admin rights.
571 be executed only using api_key belonging to user with admin rights.
546
572
547
573
548 INPUT::
574 INPUT::
549
575
550 id : <id_for_response>
576 id : <id_for_response>
551 api_key : "<api_key>"
577 api_key : "<api_key>"
552 method : "get_repo"
578 method : "get_repo"
553 args: {
579 args: {
554 "repoid" : "<reponame or repo_id>"
580 "repoid" : "<reponame or repo_id>"
555 }
581 }
556
582
557 OUTPUT::
583 OUTPUT::
558
584
559 id : <id_given_in_input>
585 id : <id_given_in_input>
560 result: None if repository does not exist or
586 result: None if repository does not exist or
561 {
587 {
562 "repo_id" : "<repo_id>",
588 "repo_id" : "<repo_id>",
563 "repo_name" : "<reponame>"
589 "repo_name" : "<reponame>"
564 "repo_type" : "<repo_type>",
590 "repo_type" : "<repo_type>",
565 "clone_uri" : "<clone_uri>",
591 "clone_uri" : "<clone_uri>",
566 "private": : "<bool>",
592 "private": : "<bool>",
567 "created_on" : "<datetimecreated>",
593 "created_on" : "<datetimecreated>",
568 "description" : "<description>",
594 "description" : "<description>",
569 "landing_rev": "<landing_rev>",
595 "landing_rev": "<landing_rev>",
570 "owner": "<repo_owner>",
596 "owner": "<repo_owner>",
571 "fork_of": "<name_of_fork_parent>",
597 "fork_of": "<name_of_fork_parent>",
572 "members" : [
598 "members" : [
573 {
599 {
574 "type": "user",
600 "type": "user",
575 "user_id" : "<user_id>",
601 "user_id" : "<user_id>",
576 "username" : "<username>",
602 "username" : "<username>",
577 "firstname": "<firstname>",
603 "firstname": "<firstname>",
578 "lastname" : "<lastname>",
604 "lastname" : "<lastname>",
579 "email" : "<email>",
605 "email" : "<email>",
580 "emails": "<list_of_all_additional_emails>",
606 "emails": "<list_of_all_additional_emails>",
581 "active" : "<bool>",
607 "active" : "<bool>",
582 "admin" :Β  "<bool>",
608 "admin" :Β  "<bool>",
583 "ldap_dn" : "<ldap_dn>",
609 "ldap_dn" : "<ldap_dn>",
584 "last_login": "<last_login>",
610 "last_login": "<last_login>",
585 "permission" : "repository.(read|write|admin)"
611 "permission" : "repository.(read|write|admin)"
586 },
612 },
587 …
613 …
588 {
614 {
589 "type": "users_group",
615 "type": "users_group",
590 "id" : "<usersgroupid>",
616 "id" : "<usersgroupid>",
591 "name" : "<usersgroupname>",
617 "name" : "<usersgroupname>",
592 "active": "<bool>",
618 "active": "<bool>",
593 "permission" : "repository.(read|write|admin)"
619 "permission" : "repository.(read|write|admin)"
594 },
620 },
595 …
621 …
596 ]
622 ]
597 }
623 }
598 error: null
624 error: null
599
625
600
626
601 get_repos
627 get_repos
602 ---------
628 ---------
603
629
604 Lists all existing repositories. This command can be executed only using api_key
630 Lists all existing repositories. This command can be executed only using api_key
605 belonging to user with admin rights
631 belonging to user with admin rights
606
632
607
633
608 INPUT::
634 INPUT::
609
635
610 id : <id_for_response>
636 id : <id_for_response>
611 api_key : "<api_key>"
637 api_key : "<api_key>"
612 method : "get_repos"
638 method : "get_repos"
613 args: { }
639 args: { }
614
640
615 OUTPUT::
641 OUTPUT::
616
642
617 id : <id_given_in_input>
643 id : <id_given_in_input>
618 result: [
644 result: [
619 {
645 {
620 "repo_id" : "<repo_id>",
646 "repo_id" : "<repo_id>",
621 "repo_name" : "<reponame>"
647 "repo_name" : "<reponame>"
622 "repo_type" : "<repo_type>",
648 "repo_type" : "<repo_type>",
623 "clone_uri" : "<clone_uri>",
649 "clone_uri" : "<clone_uri>",
624 "private": : "<bool>",
650 "private": : "<bool>",
625 "created_on" : "<datetimecreated>",
651 "created_on" : "<datetimecreated>",
626 "description" : "<description>",
652 "description" : "<description>",
627 "landing_rev": "<landing_rev>",
653 "landing_rev": "<landing_rev>",
628 "owner": "<repo_owner>",
654 "owner": "<repo_owner>",
629 "fork_of": "<name_of_fork_parent>",
655 "fork_of": "<name_of_fork_parent>",
630 },
656 },
631 …
657 …
632 ]
658 ]
633 error: null
659 error: null
634
660
635
661
636 get_repo_nodes
662 get_repo_nodes
637 --------------
663 --------------
638
664
639 returns a list of nodes and it's children in a flat list for a given path
665 returns a list of nodes and it's children in a flat list for a given path
640 at given revision. It's possible to specify ret_type to show only `files` or
666 at given revision. It's possible to specify ret_type to show only `files` or
641 `dirs`. This command can be executed only using api_key belonging to user
667 `dirs`. This command can be executed only using api_key belonging to user
642 with admin rights
668 with admin rights
643
669
644
670
645 INPUT::
671 INPUT::
646
672
647 id : <id_for_response>
673 id : <id_for_response>
648 api_key : "<api_key>"
674 api_key : "<api_key>"
649 method : "get_repo_nodes"
675 method : "get_repo_nodes"
650 args: {
676 args: {
651 "repoid" : "<reponame or repo_id>"
677 "repoid" : "<reponame or repo_id>"
652 "revision" : "<revision>",
678 "revision" : "<revision>",
653 "root_path" : "<root_path>",
679 "root_path" : "<root_path>",
654 "ret_type" : "<ret_type> = Optional('all')"
680 "ret_type" : "<ret_type> = Optional('all')"
655 }
681 }
656
682
657 OUTPUT::
683 OUTPUT::
658
684
659 id : <id_given_in_input>
685 id : <id_given_in_input>
660 result: [
686 result: [
661 {
687 {
662 "name" : "<name>"
688 "name" : "<name>"
663 "type" : "<type>",
689 "type" : "<type>",
664 },
690 },
665 …
691 …
666 ]
692 ]
667 error: null
693 error: null
668
694
669
695
670 create_repo
696 create_repo
671 -----------
697 -----------
672
698
673 Creates a repository. This command can be executed only using api_key
699 Creates a repository. This command can be executed only using api_key
674 belonging to user with admin rights.
700 belonging to user with admin rights.
675 If repository name contains "/", all needed repository groups will be created.
701 If repository name contains "/", all needed repository groups will be created.
676 For example "foo/bar/baz" will create groups "foo", "bar" (with "foo" as parent),
702 For example "foo/bar/baz" will create groups "foo", "bar" (with "foo" as parent),
677 and create "baz" repository with "bar" as group.
703 and create "baz" repository with "bar" as group.
678
704
679
705
680 INPUT::
706 INPUT::
681
707
682 id : <id_for_response>
708 id : <id_for_response>
683 api_key : "<api_key>"
709 api_key : "<api_key>"
684 method : "create_repo"
710 method : "create_repo"
685 args: {
711 args: {
686 "repo_name" : "<reponame>",
712 "repo_name" : "<reponame>",
687 "owner" : "<onwer_name_or_id>",
713 "owner" : "<onwer_name_or_id>",
688 "repo_type" : "<repo_type>",
714 "repo_type" : "<repo_type>",
689 "description" : "<description> = Optional('')",
715 "description" : "<description> = Optional('')",
690 "private" : "<bool> = Optional(False)",
716 "private" : "<bool> = Optional(False)",
691 "clone_uri" : "<clone_uri> = Optional(None)",
717 "clone_uri" : "<clone_uri> = Optional(None)",
692 "landing_rev" : "<landing_rev> = Optional('tip')",
718 "landing_rev" : "<landing_rev> = Optional('tip')",
693 }
719 }
694
720
695 OUTPUT::
721 OUTPUT::
696
722
697 id : <id_given_in_input>
723 id : <id_given_in_input>
698 result: {
724 result: {
699 "msg": "Created new repository `<reponame>`",
725 "msg": "Created new repository `<reponame>`",
700 "repo": {
726 "repo": {
701 "repo_id" : "<repo_id>",
727 "repo_id" : "<repo_id>",
702 "repo_name" : "<reponame>"
728 "repo_name" : "<reponame>"
703 "repo_type" : "<repo_type>",
729 "repo_type" : "<repo_type>",
704 "clone_uri" : "<clone_uri>",
730 "clone_uri" : "<clone_uri>",
705 "private": : "<bool>",
731 "private": : "<bool>",
706 "created_on" : "<datetimecreated>",
732 "created_on" : "<datetimecreated>",
707 "description" : "<description>",
733 "description" : "<description>",
708 "landing_rev": "<landing_rev>",
734 "landing_rev": "<landing_rev>",
709 "owner": "<repo_owner>",
735 "owner": "<repo_owner>",
710 "fork_of": "<name_of_fork_parent>",
736 "fork_of": "<name_of_fork_parent>",
711 },
737 },
712 }
738 }
713 error: null
739 error: null
714
740
715
741
716 delete_repo
742 delete_repo
717 -----------
743 -----------
718
744
719 Deletes a repository. This command can be executed only using api_key
745 Deletes a repository. This command can be executed only using api_key
720 belonging to user with admin rights.
746 belonging to user with admin rights.
721
747
722
748
723 INPUT::
749 INPUT::
724
750
725 id : <id_for_response>
751 id : <id_for_response>
726 api_key : "<api_key>"
752 api_key : "<api_key>"
727 method : "delete_repo"
753 method : "delete_repo"
728 args: {
754 args: {
729 "repoid" : "<reponame or repo_id>"
755 "repoid" : "<reponame or repo_id>"
730 }
756 }
731
757
732 OUTPUT::
758 OUTPUT::
733
759
734 id : <id_given_in_input>
760 id : <id_given_in_input>
735 result: {
761 result: {
736 "msg": "Deleted repository `<reponame>`",
762 "msg": "Deleted repository `<reponame>`",
737 "success": true
763 "success": true
738 }
764 }
739 error: null
765 error: null
740
766
741
767
742 grant_user_permission
768 grant_user_permission
743 ---------------------
769 ---------------------
744
770
745 Grant permission for user on given repository, or update existing one
771 Grant permission for user on given repository, or update existing one
746 if found. This command can be executed only using api_key belonging to user
772 if found. This command can be executed only using api_key belonging to user
747 with admin rights.
773 with admin rights.
748
774
749
775
750 INPUT::
776 INPUT::
751
777
752 id : <id_for_response>
778 id : <id_for_response>
753 api_key : "<api_key>"
779 api_key : "<api_key>"
754 method : "grant_user_permission"
780 method : "grant_user_permission"
755 args: {
781 args: {
756 "repoid" : "<reponame or repo_id>"
782 "repoid" : "<reponame or repo_id>"
757 "userid" : "<username or user_id>"
783 "userid" : "<username or user_id>"
758 "perm" : "(repository.(none|read|write|admin))",
784 "perm" : "(repository.(none|read|write|admin))",
759 }
785 }
760
786
761 OUTPUT::
787 OUTPUT::
762
788
763 id : <id_given_in_input>
789 id : <id_given_in_input>
764 result: {
790 result: {
765 "msg" : "Granted perm: `<perm>` for user: `<username>` in repo: `<reponame>`",
791 "msg" : "Granted perm: `<perm>` for user: `<username>` in repo: `<reponame>`",
766 "success": true
792 "success": true
767 }
793 }
768 error: null
794 error: null
769
795
770
796
771 revoke_user_permission
797 revoke_user_permission
772 ----------------------
798 ----------------------
773
799
774 Revoke permission for user on given repository. This command can be executed
800 Revoke permission for user on given repository. This command can be executed
775 only using api_key belonging to user with admin rights.
801 only using api_key belonging to user with admin rights.
776
802
777
803
778 INPUT::
804 INPUT::
779
805
780 id : <id_for_response>
806 id : <id_for_response>
781 api_key : "<api_key>"
807 api_key : "<api_key>"
782 method : "revoke_user_permission"
808 method : "revoke_user_permission"
783 args: {
809 args: {
784 "repoid" : "<reponame or repo_id>"
810 "repoid" : "<reponame or repo_id>"
785 "userid" : "<username or user_id>"
811 "userid" : "<username or user_id>"
786 }
812 }
787
813
788 OUTPUT::
814 OUTPUT::
789
815
790 id : <id_given_in_input>
816 id : <id_given_in_input>
791 result: {
817 result: {
792 "msg" : "Revoked perm for user: `<username>` in repo: `<reponame>`",
818 "msg" : "Revoked perm for user: `<username>` in repo: `<reponame>`",
793 "success": true
819 "success": true
794 }
820 }
795 error: null
821 error: null
796
822
797
823
798 grant_users_group_permission
824 grant_users_group_permission
799 ----------------------------
825 ----------------------------
800
826
801 Grant permission for users group on given repository, or update
827 Grant permission for users group on given repository, or update
802 existing one if found. This command can be executed only using
828 existing one if found. This command can be executed only using
803 api_key belonging to user with admin rights.
829 api_key belonging to user with admin rights.
804
830
805
831
806 INPUT::
832 INPUT::
807
833
808 id : <id_for_response>
834 id : <id_for_response>
809 api_key : "<api_key>"
835 api_key : "<api_key>"
810 method : "grant_users_group_permission"
836 method : "grant_users_group_permission"
811 args: {
837 args: {
812 "repoid" : "<reponame or repo_id>"
838 "repoid" : "<reponame or repo_id>"
813 "usersgroupid" : "<users group id or name>"
839 "usersgroupid" : "<users group id or name>"
814 "perm" : "(repository.(none|read|write|admin))",
840 "perm" : "(repository.(none|read|write|admin))",
815 }
841 }
816
842
817 OUTPUT::
843 OUTPUT::
818
844
819 id : <id_given_in_input>
845 id : <id_given_in_input>
820 result: {
846 result: {
821 "msg" : "Granted perm: `<perm>` for group: `<usersgroupname>` in repo: `<reponame>`",
847 "msg" : "Granted perm: `<perm>` for group: `<usersgroupname>` in repo: `<reponame>`",
822 "success": true
848 "success": true
823 }
849 }
824 error: null
850 error: null
825
851
826
852
827 revoke_users_group_permission
853 revoke_users_group_permission
828 -----------------------------
854 -----------------------------
829
855
830 Revoke permission for users group on given repository.This command can be
856 Revoke permission for users group on given repository.This command can be
831 executed only using api_key belonging to user with admin rights.
857 executed only using api_key belonging to user with admin rights.
832
858
833 INPUT::
859 INPUT::
834
860
835 id : <id_for_response>
861 id : <id_for_response>
836 api_key : "<api_key>"
862 api_key : "<api_key>"
837 method : "revoke_users_group_permission"
863 method : "revoke_users_group_permission"
838 args: {
864 args: {
839 "repoid" : "<reponame or repo_id>"
865 "repoid" : "<reponame or repo_id>"
840 "usersgroupid" : "<users group id or name>"
866 "usersgroupid" : "<users group id or name>"
841 }
867 }
842
868
843 OUTPUT::
869 OUTPUT::
844
870
845 id : <id_given_in_input>
871 id : <id_given_in_input>
846 result: {
872 result: {
847 "msg" : "Revoked perm for group: `<usersgroupname>` in repo: `<reponame>`",
873 "msg" : "Revoked perm for group: `<usersgroupname>` in repo: `<reponame>`",
848 "success": true
874 "success": true
849 }
875 }
850 error: null No newline at end of file
876 error: null
@@ -1,784 +1,812 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, AuthUser
33 HasPermissionAnyDecorator, PasswordGenerator, AuthUser
34 from rhodecode.lib.utils import map_groups, repo2db_mapper
34 from rhodecode.lib.utils import map_groups, repo2db_mapper
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.repo import RepoModel
37 from rhodecode.model.repo import RepoModel
38 from rhodecode.model.user import UserModel
38 from rhodecode.model.user import UserModel
39 from rhodecode.model.users_group import UsersGroupModel
39 from rhodecode.model.users_group import UsersGroupModel
40 from rhodecode.model.permission import PermissionModel
40 from rhodecode.model.permission import PermissionModel
41 from rhodecode.model.db import Repository
41
42
42 log = logging.getLogger(__name__)
43 log = logging.getLogger(__name__)
43
44
44
45
45 class Optional(object):
46 class Optional(object):
46 """
47 """
47 Defines an optional parameter::
48 Defines an optional parameter::
48
49
49 param = param.getval() if isinstance(param, Optional) else param
50 param = param.getval() if isinstance(param, Optional) else param
50 param = param() if isinstance(param, Optional) else param
51 param = param() if isinstance(param, Optional) else param
51
52
52 is equivalent of::
53 is equivalent of::
53
54
54 param = Optional.extract(param)
55 param = Optional.extract(param)
55
56
56 """
57 """
57 def __init__(self, type_):
58 def __init__(self, type_):
58 self.type_ = type_
59 self.type_ = type_
59
60
60 def __repr__(self):
61 def __repr__(self):
61 return '<Optional:%s>' % self.type_.__repr__()
62 return '<Optional:%s>' % self.type_.__repr__()
62
63
63 def __call__(self):
64 def __call__(self):
64 return self.getval()
65 return self.getval()
65
66
66 def getval(self):
67 def getval(self):
67 """
68 """
68 returns value from this Optional instance
69 returns value from this Optional instance
69 """
70 """
70 return self.type_
71 return self.type_
71
72
72 @classmethod
73 @classmethod
73 def extract(cls, val):
74 def extract(cls, val):
74 if isinstance(val, cls):
75 if isinstance(val, cls):
75 return val.getval()
76 return val.getval()
76 return val
77 return val
77
78
78
79
79 def get_user_or_error(userid):
80 def get_user_or_error(userid):
80 """
81 """
81 Get user by id or name or return JsonRPCError if not found
82 Get user by id or name or return JsonRPCError if not found
82
83
83 :param userid:
84 :param userid:
84 """
85 """
85 user = UserModel().get_user(userid)
86 user = UserModel().get_user(userid)
86 if user is None:
87 if user is None:
87 raise JSONRPCError("user `%s` does not exist" % userid)
88 raise JSONRPCError("user `%s` does not exist" % userid)
88 return user
89 return user
89
90
90
91
91 def get_repo_or_error(repoid):
92 def get_repo_or_error(repoid):
92 """
93 """
93 Get repo by id or name or return JsonRPCError if not found
94 Get repo by id or name or return JsonRPCError if not found
94
95
95 :param userid:
96 :param userid:
96 """
97 """
97 repo = RepoModel().get_repo(repoid)
98 repo = RepoModel().get_repo(repoid)
98 if repo is None:
99 if repo is None:
99 raise JSONRPCError('repository `%s` does not exist' % (repoid))
100 raise JSONRPCError('repository `%s` does not exist' % (repoid))
100 return repo
101 return repo
101
102
102
103
103 def get_users_group_or_error(usersgroupid):
104 def get_users_group_or_error(usersgroupid):
104 """
105 """
105 Get users group by id or name or return JsonRPCError if not found
106 Get users group by id or name or return JsonRPCError if not found
106
107
107 :param userid:
108 :param userid:
108 """
109 """
109 users_group = UsersGroupModel().get_group(usersgroupid)
110 users_group = UsersGroupModel().get_group(usersgroupid)
110 if users_group is None:
111 if users_group is None:
111 raise JSONRPCError('users group `%s` does not exist' % usersgroupid)
112 raise JSONRPCError('users group `%s` does not exist' % usersgroupid)
112 return users_group
113 return users_group
113
114
114
115
115 def get_perm_or_error(permid):
116 def get_perm_or_error(permid):
116 """
117 """
117 Get permission by id or name or return JsonRPCError if not found
118 Get permission by id or name or return JsonRPCError if not found
118
119
119 :param userid:
120 :param userid:
120 """
121 """
121 perm = PermissionModel().get_permission_by_name(permid)
122 perm = PermissionModel().get_permission_by_name(permid)
122 if perm is None:
123 if perm is None:
123 raise JSONRPCError('permission `%s` does not exist' % (permid))
124 raise JSONRPCError('permission `%s` does not exist' % (permid))
124 return perm
125 return perm
125
126
126
127
127 class ApiController(JSONRPCController):
128 class ApiController(JSONRPCController):
128 """
129 """
129 API Controller
130 API Controller
130
131
131
132
132 Each method needs to have USER as argument this is then based on given
133 Each method needs to have USER as argument this is then based on given
133 API_KEY propagated as instance of user object
134 API_KEY propagated as instance of user object
134
135
135 Preferably this should be first argument also
136 Preferably this should be first argument also
136
137
137
138
138 Each function should also **raise** JSONRPCError for any
139 Each function should also **raise** JSONRPCError for any
139 errors that happens
140 errors that happens
140
141
141 """
142 """
142
143
143 @HasPermissionAllDecorator('hg.admin')
144 @HasPermissionAllDecorator('hg.admin')
144 def pull(self, apiuser, repoid):
145 def pull(self, apiuser, repoid):
145 """
146 """
146 Dispatch pull action on given repo
147 Dispatch pull action on given repo
147
148
148 :param apiuser:
149 :param apiuser:
149 :param repoid:
150 :param repoid:
150 """
151 """
151
152
152 repo = get_repo_or_error(repoid)
153 repo = get_repo_or_error(repoid)
153
154
154 try:
155 try:
155 ScmModel().pull_changes(repo.repo_name,
156 ScmModel().pull_changes(repo.repo_name,
156 self.rhodecode_user.username)
157 self.rhodecode_user.username)
157 return 'Pulled from `%s`' % repo.repo_name
158 return 'Pulled from `%s`' % repo.repo_name
158 except Exception:
159 except Exception:
159 log.error(traceback.format_exc())
160 log.error(traceback.format_exc())
160 raise JSONRPCError(
161 raise JSONRPCError(
161 'Unable to pull changes from `%s`' % repo.repo_name
162 'Unable to pull changes from `%s`' % repo.repo_name
162 )
163 )
163
164
164 @HasPermissionAllDecorator('hg.admin')
165 @HasPermissionAllDecorator('hg.admin')
165 def rescan_repos(self, apiuser, remove_obsolete=Optional(False)):
166 def rescan_repos(self, apiuser, remove_obsolete=Optional(False)):
166 """
167 """
167 Dispatch rescan repositories action. If remove_obsolete is set
168 Dispatch rescan repositories action. If remove_obsolete is set
168 than also delete repos that are in database but not in the filesystem.
169 than also delete repos that are in database but not in the filesystem.
169 aka "clean zombies"
170 aka "clean zombies"
170
171
171 :param apiuser:
172 :param apiuser:
172 :param remove_obsolete:
173 :param remove_obsolete:
173 """
174 """
174
175
175 try:
176 try:
176 rm_obsolete = Optional.extract(remove_obsolete)
177 rm_obsolete = Optional.extract(remove_obsolete)
177 added, removed = repo2db_mapper(ScmModel().repo_scan(),
178 added, removed = repo2db_mapper(ScmModel().repo_scan(),
178 remove_obsolete=rm_obsolete)
179 remove_obsolete=rm_obsolete)
179 return {'added': added, 'removed': removed}
180 return {'added': added, 'removed': removed}
180 except Exception:
181 except Exception:
181 log.error(traceback.format_exc())
182 log.error(traceback.format_exc())
182 raise JSONRPCError(
183 raise JSONRPCError(
183 'Unable to rescan repositories'
184 'Error occurred during rescan repositories action'
185 )
186
187 @HasPermissionAllDecorator('hg.admin')
188 def lock(self, apiuser, repoid, userid, locked):
189 """
190 Set locking state on particular repository by given user
191
192 :param apiuser:
193 :param repoid:
194 :param userid:
195 :param locked:
196 """
197 repo = get_repo_or_error(repoid)
198 user = get_user_or_error(userid)
199 locked = bool(locked)
200 try:
201 if locked:
202 Repository.lock(repo, user.user_id)
203 else:
204 Repository.unlock(repo)
205
206 return ('User `%s` set lock state for repo `%s` to `%s`'
207 % (user.username, repo.repo_name, locked))
208 except Exception:
209 log.error(traceback.format_exc())
210 raise JSONRPCError(
211 'Error occurred locking repository `%s`' % repo.repo_name
184 )
212 )
185
213
186 @HasPermissionAllDecorator('hg.admin')
214 @HasPermissionAllDecorator('hg.admin')
187 def get_user(self, apiuser, userid):
215 def get_user(self, apiuser, userid):
188 """"
216 """"
189 Get a user by username
217 Get a user by username
190
218
191 :param apiuser:
219 :param apiuser:
192 :param userid:
220 :param userid:
193 """
221 """
194
222
195 user = get_user_or_error(userid)
223 user = get_user_or_error(userid)
196 data = user.get_api_data()
224 data = user.get_api_data()
197 data['permissions'] = AuthUser(user_id=user.user_id).permissions
225 data['permissions'] = AuthUser(user_id=user.user_id).permissions
198 return data
226 return data
199
227
200 @HasPermissionAllDecorator('hg.admin')
228 @HasPermissionAllDecorator('hg.admin')
201 def get_users(self, apiuser):
229 def get_users(self, apiuser):
202 """"
230 """"
203 Get all users
231 Get all users
204
232
205 :param apiuser:
233 :param apiuser:
206 """
234 """
207
235
208 result = []
236 result = []
209 for user in UserModel().get_all():
237 for user in UserModel().get_all():
210 result.append(user.get_api_data())
238 result.append(user.get_api_data())
211 return result
239 return result
212
240
213 @HasPermissionAllDecorator('hg.admin')
241 @HasPermissionAllDecorator('hg.admin')
214 def create_user(self, apiuser, username, email, password,
242 def create_user(self, apiuser, username, email, password,
215 firstname=Optional(None), lastname=Optional(None),
243 firstname=Optional(None), lastname=Optional(None),
216 active=Optional(True), admin=Optional(False),
244 active=Optional(True), admin=Optional(False),
217 ldap_dn=Optional(None)):
245 ldap_dn=Optional(None)):
218 """
246 """
219 Create new user
247 Create new user
220
248
221 :param apiuser:
249 :param apiuser:
222 :param username:
250 :param username:
223 :param email:
251 :param email:
224 :param password:
252 :param password:
225 :param firstname:
253 :param firstname:
226 :param lastname:
254 :param lastname:
227 :param active:
255 :param active:
228 :param admin:
256 :param admin:
229 :param ldap_dn:
257 :param ldap_dn:
230 """
258 """
231
259
232 if UserModel().get_by_username(username):
260 if UserModel().get_by_username(username):
233 raise JSONRPCError("user `%s` already exist" % username)
261 raise JSONRPCError("user `%s` already exist" % username)
234
262
235 if UserModel().get_by_email(email, case_insensitive=True):
263 if UserModel().get_by_email(email, case_insensitive=True):
236 raise JSONRPCError("email `%s` already exist" % email)
264 raise JSONRPCError("email `%s` already exist" % email)
237
265
238 if ldap_dn:
266 if ldap_dn:
239 # generate temporary password if ldap_dn
267 # generate temporary password if ldap_dn
240 password = PasswordGenerator().gen_password(length=8)
268 password = PasswordGenerator().gen_password(length=8)
241
269
242 try:
270 try:
243 user = UserModel().create_or_update(
271 user = UserModel().create_or_update(
244 username=Optional.extract(username),
272 username=Optional.extract(username),
245 password=Optional.extract(password),
273 password=Optional.extract(password),
246 email=Optional.extract(email),
274 email=Optional.extract(email),
247 firstname=Optional.extract(firstname),
275 firstname=Optional.extract(firstname),
248 lastname=Optional.extract(lastname),
276 lastname=Optional.extract(lastname),
249 active=Optional.extract(active),
277 active=Optional.extract(active),
250 admin=Optional.extract(admin),
278 admin=Optional.extract(admin),
251 ldap_dn=Optional.extract(ldap_dn)
279 ldap_dn=Optional.extract(ldap_dn)
252 )
280 )
253 Session().commit()
281 Session().commit()
254 return dict(
282 return dict(
255 msg='created new user `%s`' % username,
283 msg='created new user `%s`' % username,
256 user=user.get_api_data()
284 user=user.get_api_data()
257 )
285 )
258 except Exception:
286 except Exception:
259 log.error(traceback.format_exc())
287 log.error(traceback.format_exc())
260 raise JSONRPCError('failed to create user `%s`' % username)
288 raise JSONRPCError('failed to create user `%s`' % username)
261
289
262 @HasPermissionAllDecorator('hg.admin')
290 @HasPermissionAllDecorator('hg.admin')
263 def update_user(self, apiuser, userid, username=Optional(None),
291 def update_user(self, apiuser, userid, username=Optional(None),
264 email=Optional(None), firstname=Optional(None),
292 email=Optional(None), firstname=Optional(None),
265 lastname=Optional(None), active=Optional(None),
293 lastname=Optional(None), active=Optional(None),
266 admin=Optional(None), ldap_dn=Optional(None),
294 admin=Optional(None), ldap_dn=Optional(None),
267 password=Optional(None)):
295 password=Optional(None)):
268 """
296 """
269 Updates given user
297 Updates given user
270
298
271 :param apiuser:
299 :param apiuser:
272 :param userid:
300 :param userid:
273 :param username:
301 :param username:
274 :param email:
302 :param email:
275 :param firstname:
303 :param firstname:
276 :param lastname:
304 :param lastname:
277 :param active:
305 :param active:
278 :param admin:
306 :param admin:
279 :param ldap_dn:
307 :param ldap_dn:
280 :param password:
308 :param password:
281 """
309 """
282
310
283 user = get_user_or_error(userid)
311 user = get_user_or_error(userid)
284
312
285 # call function and store only updated arguments
313 # call function and store only updated arguments
286 updates = {}
314 updates = {}
287
315
288 def store_update(attr, name):
316 def store_update(attr, name):
289 if not isinstance(attr, Optional):
317 if not isinstance(attr, Optional):
290 updates[name] = attr
318 updates[name] = attr
291
319
292 try:
320 try:
293
321
294 store_update(username, 'username')
322 store_update(username, 'username')
295 store_update(password, 'password')
323 store_update(password, 'password')
296 store_update(email, 'email')
324 store_update(email, 'email')
297 store_update(firstname, 'name')
325 store_update(firstname, 'name')
298 store_update(lastname, 'lastname')
326 store_update(lastname, 'lastname')
299 store_update(active, 'active')
327 store_update(active, 'active')
300 store_update(admin, 'admin')
328 store_update(admin, 'admin')
301 store_update(ldap_dn, 'ldap_dn')
329 store_update(ldap_dn, 'ldap_dn')
302
330
303 user = UserModel().update_user(user, **updates)
331 user = UserModel().update_user(user, **updates)
304 Session().commit()
332 Session().commit()
305 return dict(
333 return dict(
306 msg='updated user ID:%s %s' % (user.user_id, user.username),
334 msg='updated user ID:%s %s' % (user.user_id, user.username),
307 user=user.get_api_data()
335 user=user.get_api_data()
308 )
336 )
309 except Exception:
337 except Exception:
310 log.error(traceback.format_exc())
338 log.error(traceback.format_exc())
311 raise JSONRPCError('failed to update user `%s`' % userid)
339 raise JSONRPCError('failed to update user `%s`' % userid)
312
340
313 @HasPermissionAllDecorator('hg.admin')
341 @HasPermissionAllDecorator('hg.admin')
314 def delete_user(self, apiuser, userid):
342 def delete_user(self, apiuser, userid):
315 """"
343 """"
316 Deletes an user
344 Deletes an user
317
345
318 :param apiuser:
346 :param apiuser:
319 :param userid:
347 :param userid:
320 """
348 """
321 user = get_user_or_error(userid)
349 user = get_user_or_error(userid)
322
350
323 try:
351 try:
324 UserModel().delete(userid)
352 UserModel().delete(userid)
325 Session().commit()
353 Session().commit()
326 return dict(
354 return dict(
327 msg='deleted user ID:%s %s' % (user.user_id, user.username),
355 msg='deleted user ID:%s %s' % (user.user_id, user.username),
328 user=None
356 user=None
329 )
357 )
330 except Exception:
358 except Exception:
331 log.error(traceback.format_exc())
359 log.error(traceback.format_exc())
332 raise JSONRPCError('failed to delete ID:%s %s' % (user.user_id,
360 raise JSONRPCError('failed to delete ID:%s %s' % (user.user_id,
333 user.username))
361 user.username))
334
362
335 @HasPermissionAllDecorator('hg.admin')
363 @HasPermissionAllDecorator('hg.admin')
336 def get_users_group(self, apiuser, usersgroupid):
364 def get_users_group(self, apiuser, usersgroupid):
337 """"
365 """"
338 Get users group by name or id
366 Get users group by name or id
339
367
340 :param apiuser:
368 :param apiuser:
341 :param usersgroupid:
369 :param usersgroupid:
342 """
370 """
343 users_group = get_users_group_or_error(usersgroupid)
371 users_group = get_users_group_or_error(usersgroupid)
344
372
345 data = users_group.get_api_data()
373 data = users_group.get_api_data()
346
374
347 members = []
375 members = []
348 for user in users_group.members:
376 for user in users_group.members:
349 user = user.user
377 user = user.user
350 members.append(user.get_api_data())
378 members.append(user.get_api_data())
351 data['members'] = members
379 data['members'] = members
352 return data
380 return data
353
381
354 @HasPermissionAllDecorator('hg.admin')
382 @HasPermissionAllDecorator('hg.admin')
355 def get_users_groups(self, apiuser):
383 def get_users_groups(self, apiuser):
356 """"
384 """"
357 Get all users groups
385 Get all users groups
358
386
359 :param apiuser:
387 :param apiuser:
360 """
388 """
361
389
362 result = []
390 result = []
363 for users_group in UsersGroupModel().get_all():
391 for users_group in UsersGroupModel().get_all():
364 result.append(users_group.get_api_data())
392 result.append(users_group.get_api_data())
365 return result
393 return result
366
394
367 @HasPermissionAllDecorator('hg.admin')
395 @HasPermissionAllDecorator('hg.admin')
368 def create_users_group(self, apiuser, group_name, active=Optional(True)):
396 def create_users_group(self, apiuser, group_name, active=Optional(True)):
369 """
397 """
370 Creates an new usergroup
398 Creates an new usergroup
371
399
372 :param apiuser:
400 :param apiuser:
373 :param group_name:
401 :param group_name:
374 :param active:
402 :param active:
375 """
403 """
376
404
377 if UsersGroupModel().get_by_name(group_name):
405 if UsersGroupModel().get_by_name(group_name):
378 raise JSONRPCError("users group `%s` already exist" % group_name)
406 raise JSONRPCError("users group `%s` already exist" % group_name)
379
407
380 try:
408 try:
381 active = Optional.extract(active)
409 active = Optional.extract(active)
382 ug = UsersGroupModel().create(name=group_name, active=active)
410 ug = UsersGroupModel().create(name=group_name, active=active)
383 Session().commit()
411 Session().commit()
384 return dict(
412 return dict(
385 msg='created new users group `%s`' % group_name,
413 msg='created new users group `%s`' % group_name,
386 users_group=ug.get_api_data()
414 users_group=ug.get_api_data()
387 )
415 )
388 except Exception:
416 except Exception:
389 log.error(traceback.format_exc())
417 log.error(traceback.format_exc())
390 raise JSONRPCError('failed to create group `%s`' % group_name)
418 raise JSONRPCError('failed to create group `%s`' % group_name)
391
419
392 @HasPermissionAllDecorator('hg.admin')
420 @HasPermissionAllDecorator('hg.admin')
393 def add_user_to_users_group(self, apiuser, usersgroupid, userid):
421 def add_user_to_users_group(self, apiuser, usersgroupid, userid):
394 """"
422 """"
395 Add a user to a users group
423 Add a user to a users group
396
424
397 :param apiuser:
425 :param apiuser:
398 :param usersgroupid:
426 :param usersgroupid:
399 :param userid:
427 :param userid:
400 """
428 """
401 user = get_user_or_error(userid)
429 user = get_user_or_error(userid)
402 users_group = get_users_group_or_error(usersgroupid)
430 users_group = get_users_group_or_error(usersgroupid)
403
431
404 try:
432 try:
405 ugm = UsersGroupModel().add_user_to_group(users_group, user)
433 ugm = UsersGroupModel().add_user_to_group(users_group, user)
406 success = True if ugm != True else False
434 success = True if ugm != True else False
407 msg = 'added member `%s` to users group `%s`' % (
435 msg = 'added member `%s` to users group `%s`' % (
408 user.username, users_group.users_group_name
436 user.username, users_group.users_group_name
409 )
437 )
410 msg = msg if success else 'User is already in that group'
438 msg = msg if success else 'User is already in that group'
411 Session().commit()
439 Session().commit()
412
440
413 return dict(
441 return dict(
414 success=success,
442 success=success,
415 msg=msg
443 msg=msg
416 )
444 )
417 except Exception:
445 except Exception:
418 log.error(traceback.format_exc())
446 log.error(traceback.format_exc())
419 raise JSONRPCError(
447 raise JSONRPCError(
420 'failed to add member to users group `%s`' % (
448 'failed to add member to users group `%s`' % (
421 users_group.users_group_name
449 users_group.users_group_name
422 )
450 )
423 )
451 )
424
452
425 @HasPermissionAllDecorator('hg.admin')
453 @HasPermissionAllDecorator('hg.admin')
426 def remove_user_from_users_group(self, apiuser, usersgroupid, userid):
454 def remove_user_from_users_group(self, apiuser, usersgroupid, userid):
427 """
455 """
428 Remove user from a group
456 Remove user from a group
429
457
430 :param apiuser:
458 :param apiuser:
431 :param usersgroupid:
459 :param usersgroupid:
432 :param userid:
460 :param userid:
433 """
461 """
434 user = get_user_or_error(userid)
462 user = get_user_or_error(userid)
435 users_group = get_users_group_or_error(usersgroupid)
463 users_group = get_users_group_or_error(usersgroupid)
436
464
437 try:
465 try:
438 success = UsersGroupModel().remove_user_from_group(users_group,
466 success = UsersGroupModel().remove_user_from_group(users_group,
439 user)
467 user)
440 msg = 'removed member `%s` from users group `%s`' % (
468 msg = 'removed member `%s` from users group `%s`' % (
441 user.username, users_group.users_group_name
469 user.username, users_group.users_group_name
442 )
470 )
443 msg = msg if success else "User wasn't in group"
471 msg = msg if success else "User wasn't in group"
444 Session().commit()
472 Session().commit()
445 return dict(success=success, msg=msg)
473 return dict(success=success, msg=msg)
446 except Exception:
474 except Exception:
447 log.error(traceback.format_exc())
475 log.error(traceback.format_exc())
448 raise JSONRPCError(
476 raise JSONRPCError(
449 'failed to remove member from users group `%s`' % (
477 'failed to remove member from users group `%s`' % (
450 users_group.users_group_name
478 users_group.users_group_name
451 )
479 )
452 )
480 )
453
481
454 @HasPermissionAnyDecorator('hg.admin')
482 @HasPermissionAnyDecorator('hg.admin')
455 def get_repo(self, apiuser, repoid):
483 def get_repo(self, apiuser, repoid):
456 """"
484 """"
457 Get repository by name
485 Get repository by name
458
486
459 :param apiuser:
487 :param apiuser:
460 :param repoid:
488 :param repoid:
461 """
489 """
462 repo = get_repo_or_error(repoid)
490 repo = get_repo_or_error(repoid)
463
491
464 members = []
492 members = []
465 for user in repo.repo_to_perm:
493 for user in repo.repo_to_perm:
466 perm = user.permission.permission_name
494 perm = user.permission.permission_name
467 user = user.user
495 user = user.user
468 user_data = user.get_api_data()
496 user_data = user.get_api_data()
469 user_data['type'] = "user"
497 user_data['type'] = "user"
470 user_data['permission'] = perm
498 user_data['permission'] = perm
471 members.append(user_data)
499 members.append(user_data)
472
500
473 for users_group in repo.users_group_to_perm:
501 for users_group in repo.users_group_to_perm:
474 perm = users_group.permission.permission_name
502 perm = users_group.permission.permission_name
475 users_group = users_group.users_group
503 users_group = users_group.users_group
476 users_group_data = users_group.get_api_data()
504 users_group_data = users_group.get_api_data()
477 users_group_data['type'] = "users_group"
505 users_group_data['type'] = "users_group"
478 users_group_data['permission'] = perm
506 users_group_data['permission'] = perm
479 members.append(users_group_data)
507 members.append(users_group_data)
480
508
481 data = repo.get_api_data()
509 data = repo.get_api_data()
482 data['members'] = members
510 data['members'] = members
483 return data
511 return data
484
512
485 @HasPermissionAnyDecorator('hg.admin')
513 @HasPermissionAnyDecorator('hg.admin')
486 def get_repos(self, apiuser):
514 def get_repos(self, apiuser):
487 """"
515 """"
488 Get all repositories
516 Get all repositories
489
517
490 :param apiuser:
518 :param apiuser:
491 """
519 """
492
520
493 result = []
521 result = []
494 for repo in RepoModel().get_all():
522 for repo in RepoModel().get_all():
495 result.append(repo.get_api_data())
523 result.append(repo.get_api_data())
496 return result
524 return result
497
525
498 @HasPermissionAnyDecorator('hg.admin')
526 @HasPermissionAnyDecorator('hg.admin')
499 def get_repo_nodes(self, apiuser, repoid, revision, root_path,
527 def get_repo_nodes(self, apiuser, repoid, revision, root_path,
500 ret_type='all'):
528 ret_type='all'):
501 """
529 """
502 returns a list of nodes and it's children
530 returns a list of nodes and it's children
503 for a given path at given revision. It's possible to specify ret_type
531 for a given path at given revision. It's possible to specify ret_type
504 to show only files or dirs
532 to show only files or dirs
505
533
506 :param apiuser:
534 :param apiuser:
507 :param repoid: name or id of repository
535 :param repoid: name or id of repository
508 :param revision: revision for which listing should be done
536 :param revision: revision for which listing should be done
509 :param root_path: path from which start displaying
537 :param root_path: path from which start displaying
510 :param ret_type: return type 'all|files|dirs' nodes
538 :param ret_type: return type 'all|files|dirs' nodes
511 """
539 """
512 repo = get_repo_or_error(repoid)
540 repo = get_repo_or_error(repoid)
513 try:
541 try:
514 _d, _f = ScmModel().get_nodes(repo, revision, root_path,
542 _d, _f = ScmModel().get_nodes(repo, revision, root_path,
515 flat=False)
543 flat=False)
516 _map = {
544 _map = {
517 'all': _d + _f,
545 'all': _d + _f,
518 'files': _f,
546 'files': _f,
519 'dirs': _d,
547 'dirs': _d,
520 }
548 }
521 return _map[ret_type]
549 return _map[ret_type]
522 except KeyError:
550 except KeyError:
523 raise JSONRPCError('ret_type must be one of %s' % _map.keys())
551 raise JSONRPCError('ret_type must be one of %s' % _map.keys())
524 except Exception:
552 except Exception:
525 log.error(traceback.format_exc())
553 log.error(traceback.format_exc())
526 raise JSONRPCError(
554 raise JSONRPCError(
527 'failed to get repo: `%s` nodes' % repo.repo_name
555 'failed to get repo: `%s` nodes' % repo.repo_name
528 )
556 )
529
557
530 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
558 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
531 def create_repo(self, apiuser, repo_name, owner, repo_type,
559 def create_repo(self, apiuser, repo_name, owner, repo_type,
532 description=Optional(''), private=Optional(False),
560 description=Optional(''), private=Optional(False),
533 clone_uri=Optional(None), landing_rev=Optional('tip')):
561 clone_uri=Optional(None), landing_rev=Optional('tip')):
534 """
562 """
535 Create repository, if clone_url is given it makes a remote clone
563 Create repository, if clone_url is given it makes a remote clone
536 if repo_name is withina group name the groups will be created
564 if repo_name is withina group name the groups will be created
537 automatically if they aren't present
565 automatically if they aren't present
538
566
539 :param apiuser:
567 :param apiuser:
540 :param repo_name:
568 :param repo_name:
541 :param onwer:
569 :param onwer:
542 :param repo_type:
570 :param repo_type:
543 :param description:
571 :param description:
544 :param private:
572 :param private:
545 :param clone_uri:
573 :param clone_uri:
546 :param landing_rev:
574 :param landing_rev:
547 """
575 """
548 owner = get_user_or_error(owner)
576 owner = get_user_or_error(owner)
549
577
550 if RepoModel().get_by_repo_name(repo_name):
578 if RepoModel().get_by_repo_name(repo_name):
551 raise JSONRPCError("repo `%s` already exist" % repo_name)
579 raise JSONRPCError("repo `%s` already exist" % repo_name)
552
580
553 private = Optional.extract(private)
581 private = Optional.extract(private)
554 clone_uri = Optional.extract(clone_uri)
582 clone_uri = Optional.extract(clone_uri)
555 description = Optional.extract(description)
583 description = Optional.extract(description)
556 landing_rev = Optional.extract(landing_rev)
584 landing_rev = Optional.extract(landing_rev)
557
585
558 try:
586 try:
559 # create structure of groups and return the last group
587 # create structure of groups and return the last group
560 group = map_groups(repo_name)
588 group = map_groups(repo_name)
561
589
562 repo = RepoModel().create_repo(
590 repo = RepoModel().create_repo(
563 repo_name=repo_name,
591 repo_name=repo_name,
564 repo_type=repo_type,
592 repo_type=repo_type,
565 description=description,
593 description=description,
566 owner=owner,
594 owner=owner,
567 private=private,
595 private=private,
568 clone_uri=clone_uri,
596 clone_uri=clone_uri,
569 repos_group=group,
597 repos_group=group,
570 landing_rev=landing_rev,
598 landing_rev=landing_rev,
571 )
599 )
572
600
573 Session().commit()
601 Session().commit()
574
602
575 return dict(
603 return dict(
576 msg="Created new repository `%s`" % (repo.repo_name),
604 msg="Created new repository `%s`" % (repo.repo_name),
577 repo=repo.get_api_data()
605 repo=repo.get_api_data()
578 )
606 )
579
607
580 except Exception:
608 except Exception:
581 log.error(traceback.format_exc())
609 log.error(traceback.format_exc())
582 raise JSONRPCError('failed to create repository `%s`' % repo_name)
610 raise JSONRPCError('failed to create repository `%s`' % repo_name)
583
611
584 @HasPermissionAnyDecorator('hg.admin')
612 @HasPermissionAnyDecorator('hg.admin')
585 def fork_repo(self, apiuser, repoid, fork_name, owner,
613 def fork_repo(self, apiuser, repoid, fork_name, owner,
586 description=Optional(''), copy_permissions=Optional(False),
614 description=Optional(''), copy_permissions=Optional(False),
587 private=Optional(False), landing_rev=Optional('tip')):
615 private=Optional(False), landing_rev=Optional('tip')):
588 repo = get_repo_or_error(repoid)
616 repo = get_repo_or_error(repoid)
589 repo_name = repo.repo_name
617 repo_name = repo.repo_name
590 owner = get_user_or_error(owner)
618 owner = get_user_or_error(owner)
591
619
592 _repo = RepoModel().get_by_repo_name(fork_name)
620 _repo = RepoModel().get_by_repo_name(fork_name)
593 if _repo:
621 if _repo:
594 type_ = 'fork' if _repo.fork else 'repo'
622 type_ = 'fork' if _repo.fork else 'repo'
595 raise JSONRPCError("%s `%s` already exist" % (type_, fork_name))
623 raise JSONRPCError("%s `%s` already exist" % (type_, fork_name))
596
624
597 try:
625 try:
598 # create structure of groups and return the last group
626 # create structure of groups and return the last group
599 group = map_groups(fork_name)
627 group = map_groups(fork_name)
600
628
601 form_data = dict(
629 form_data = dict(
602 repo_name=fork_name,
630 repo_name=fork_name,
603 repo_name_full=fork_name,
631 repo_name_full=fork_name,
604 repo_group=group,
632 repo_group=group,
605 repo_type=repo.repo_type,
633 repo_type=repo.repo_type,
606 description=Optional.extract(description),
634 description=Optional.extract(description),
607 private=Optional.extract(private),
635 private=Optional.extract(private),
608 copy_permissions=Optional.extract(copy_permissions),
636 copy_permissions=Optional.extract(copy_permissions),
609 landing_rev=Optional.extract(landing_rev),
637 landing_rev=Optional.extract(landing_rev),
610 update_after_clone=False,
638 update_after_clone=False,
611 fork_parent_id=repo.repo_id,
639 fork_parent_id=repo.repo_id,
612 )
640 )
613 RepoModel().create_fork(form_data, cur_user=owner)
641 RepoModel().create_fork(form_data, cur_user=owner)
614 return dict(
642 return dict(
615 msg='Created fork of `%s` as `%s`' % (repo.repo_name,
643 msg='Created fork of `%s` as `%s`' % (repo.repo_name,
616 fork_name),
644 fork_name),
617 success=True # cannot return the repo data here since fork
645 success=True # cannot return the repo data here since fork
618 # cann be done async
646 # cann be done async
619 )
647 )
620 except Exception:
648 except Exception:
621 log.error(traceback.format_exc())
649 log.error(traceback.format_exc())
622 raise JSONRPCError(
650 raise JSONRPCError(
623 'failed to fork repository `%s` as `%s`' % (repo_name,
651 'failed to fork repository `%s` as `%s`' % (repo_name,
624 fork_name)
652 fork_name)
625 )
653 )
626
654
627 @HasPermissionAnyDecorator('hg.admin')
655 @HasPermissionAnyDecorator('hg.admin')
628 def delete_repo(self, apiuser, repoid):
656 def delete_repo(self, apiuser, repoid):
629 """
657 """
630 Deletes a given repository
658 Deletes a given repository
631
659
632 :param apiuser:
660 :param apiuser:
633 :param repoid:
661 :param repoid:
634 """
662 """
635 repo = get_repo_or_error(repoid)
663 repo = get_repo_or_error(repoid)
636
664
637 try:
665 try:
638 RepoModel().delete(repo)
666 RepoModel().delete(repo)
639 Session().commit()
667 Session().commit()
640 return dict(
668 return dict(
641 msg='Deleted repository `%s`' % repo.repo_name,
669 msg='Deleted repository `%s`' % repo.repo_name,
642 success=True
670 success=True
643 )
671 )
644 except Exception:
672 except Exception:
645 log.error(traceback.format_exc())
673 log.error(traceback.format_exc())
646 raise JSONRPCError(
674 raise JSONRPCError(
647 'failed to delete repository `%s`' % repo.repo_name
675 'failed to delete repository `%s`' % repo.repo_name
648 )
676 )
649
677
650 @HasPermissionAnyDecorator('hg.admin')
678 @HasPermissionAnyDecorator('hg.admin')
651 def grant_user_permission(self, apiuser, repoid, userid, perm):
679 def grant_user_permission(self, apiuser, repoid, userid, perm):
652 """
680 """
653 Grant permission for user on given repository, or update existing one
681 Grant permission for user on given repository, or update existing one
654 if found
682 if found
655
683
656 :param repoid:
684 :param repoid:
657 :param userid:
685 :param userid:
658 :param perm:
686 :param perm:
659 """
687 """
660 repo = get_repo_or_error(repoid)
688 repo = get_repo_or_error(repoid)
661 user = get_user_or_error(userid)
689 user = get_user_or_error(userid)
662 perm = get_perm_or_error(perm)
690 perm = get_perm_or_error(perm)
663
691
664 try:
692 try:
665
693
666 RepoModel().grant_user_permission(repo=repo, user=user, perm=perm)
694 RepoModel().grant_user_permission(repo=repo, user=user, perm=perm)
667
695
668 Session().commit()
696 Session().commit()
669 return dict(
697 return dict(
670 msg='Granted perm: `%s` for user: `%s` in repo: `%s`' % (
698 msg='Granted perm: `%s` for user: `%s` in repo: `%s`' % (
671 perm.permission_name, user.username, repo.repo_name
699 perm.permission_name, user.username, repo.repo_name
672 ),
700 ),
673 success=True
701 success=True
674 )
702 )
675 except Exception:
703 except Exception:
676 log.error(traceback.format_exc())
704 log.error(traceback.format_exc())
677 raise JSONRPCError(
705 raise JSONRPCError(
678 'failed to edit permission for user: `%s` in repo: `%s`' % (
706 'failed to edit permission for user: `%s` in repo: `%s`' % (
679 userid, repoid
707 userid, repoid
680 )
708 )
681 )
709 )
682
710
683 @HasPermissionAnyDecorator('hg.admin')
711 @HasPermissionAnyDecorator('hg.admin')
684 def revoke_user_permission(self, apiuser, repoid, userid):
712 def revoke_user_permission(self, apiuser, repoid, userid):
685 """
713 """
686 Revoke permission for user on given repository
714 Revoke permission for user on given repository
687
715
688 :param apiuser:
716 :param apiuser:
689 :param repoid:
717 :param repoid:
690 :param userid:
718 :param userid:
691 """
719 """
692
720
693 repo = get_repo_or_error(repoid)
721 repo = get_repo_or_error(repoid)
694 user = get_user_or_error(userid)
722 user = get_user_or_error(userid)
695 try:
723 try:
696
724
697 RepoModel().revoke_user_permission(repo=repo, user=user)
725 RepoModel().revoke_user_permission(repo=repo, user=user)
698
726
699 Session().commit()
727 Session().commit()
700 return dict(
728 return dict(
701 msg='Revoked perm for user: `%s` in repo: `%s`' % (
729 msg='Revoked perm for user: `%s` in repo: `%s`' % (
702 user.username, repo.repo_name
730 user.username, repo.repo_name
703 ),
731 ),
704 success=True
732 success=True
705 )
733 )
706 except Exception:
734 except Exception:
707 log.error(traceback.format_exc())
735 log.error(traceback.format_exc())
708 raise JSONRPCError(
736 raise JSONRPCError(
709 'failed to edit permission for user: `%s` in repo: `%s`' % (
737 'failed to edit permission for user: `%s` in repo: `%s`' % (
710 userid, repoid
738 userid, repoid
711 )
739 )
712 )
740 )
713
741
714 @HasPermissionAnyDecorator('hg.admin')
742 @HasPermissionAnyDecorator('hg.admin')
715 def grant_users_group_permission(self, apiuser, repoid, usersgroupid,
743 def grant_users_group_permission(self, apiuser, repoid, usersgroupid,
716 perm):
744 perm):
717 """
745 """
718 Grant permission for users group on given repository, or update
746 Grant permission for users group on given repository, or update
719 existing one if found
747 existing one if found
720
748
721 :param apiuser:
749 :param apiuser:
722 :param repoid:
750 :param repoid:
723 :param usersgroupid:
751 :param usersgroupid:
724 :param perm:
752 :param perm:
725 """
753 """
726 repo = get_repo_or_error(repoid)
754 repo = get_repo_or_error(repoid)
727 perm = get_perm_or_error(perm)
755 perm = get_perm_or_error(perm)
728 users_group = get_users_group_or_error(usersgroupid)
756 users_group = get_users_group_or_error(usersgroupid)
729
757
730 try:
758 try:
731 RepoModel().grant_users_group_permission(repo=repo,
759 RepoModel().grant_users_group_permission(repo=repo,
732 group_name=users_group,
760 group_name=users_group,
733 perm=perm)
761 perm=perm)
734
762
735 Session().commit()
763 Session().commit()
736 return dict(
764 return dict(
737 msg='Granted perm: `%s` for users group: `%s` in '
765 msg='Granted perm: `%s` for users group: `%s` in '
738 'repo: `%s`' % (
766 'repo: `%s`' % (
739 perm.permission_name, users_group.users_group_name,
767 perm.permission_name, users_group.users_group_name,
740 repo.repo_name
768 repo.repo_name
741 ),
769 ),
742 success=True
770 success=True
743 )
771 )
744 except Exception:
772 except Exception:
745 print traceback.format_exc()
773 print traceback.format_exc()
746 log.error(traceback.format_exc())
774 log.error(traceback.format_exc())
747 raise JSONRPCError(
775 raise JSONRPCError(
748 'failed to edit permission for users group: `%s` in '
776 'failed to edit permission for users group: `%s` in '
749 'repo: `%s`' % (
777 'repo: `%s`' % (
750 usersgroupid, repo.repo_name
778 usersgroupid, repo.repo_name
751 )
779 )
752 )
780 )
753
781
754 @HasPermissionAnyDecorator('hg.admin')
782 @HasPermissionAnyDecorator('hg.admin')
755 def revoke_users_group_permission(self, apiuser, repoid, usersgroupid):
783 def revoke_users_group_permission(self, apiuser, repoid, usersgroupid):
756 """
784 """
757 Revoke permission for users group on given repository
785 Revoke permission for users group on given repository
758
786
759 :param apiuser:
787 :param apiuser:
760 :param repoid:
788 :param repoid:
761 :param usersgroupid:
789 :param usersgroupid:
762 """
790 """
763 repo = get_repo_or_error(repoid)
791 repo = get_repo_or_error(repoid)
764 users_group = get_users_group_or_error(usersgroupid)
792 users_group = get_users_group_or_error(usersgroupid)
765
793
766 try:
794 try:
767 RepoModel().revoke_users_group_permission(repo=repo,
795 RepoModel().revoke_users_group_permission(repo=repo,
768 group_name=users_group)
796 group_name=users_group)
769
797
770 Session().commit()
798 Session().commit()
771 return dict(
799 return dict(
772 msg='Revoked perm for users group: `%s` in repo: `%s`' % (
800 msg='Revoked perm for users group: `%s` in repo: `%s`' % (
773 users_group.users_group_name, repo.repo_name
801 users_group.users_group_name, repo.repo_name
774 ),
802 ),
775 success=True
803 success=True
776 )
804 )
777 except Exception:
805 except Exception:
778 log.error(traceback.format_exc())
806 log.error(traceback.format_exc())
779 raise JSONRPCError(
807 raise JSONRPCError(
780 'failed to edit permission for users group: `%s` in '
808 'failed to edit permission for users group: `%s` in '
781 'repo: `%s`' % (
809 'repo: `%s`' % (
782 users_group.users_group_name, repo.repo_name
810 users_group.users_group_name, repo.repo_name
783 )
811 )
784 )
812 )
@@ -1,1008 +1,1043 b''
1 from __future__ import with_statement
1 from __future__ import with_statement
2 import random
2 import random
3 import mock
3 import mock
4
4
5 from rhodecode.tests import *
5 from rhodecode.tests import *
6 from rhodecode.lib.compat import json
6 from rhodecode.lib.compat import json
7 from rhodecode.lib.auth import AuthUser
7 from rhodecode.lib.auth import AuthUser
8 from rhodecode.model.user import UserModel
8 from rhodecode.model.user import UserModel
9 from rhodecode.model.users_group import UsersGroupModel
9 from rhodecode.model.users_group import UsersGroupModel
10 from rhodecode.model.repo import RepoModel
10 from rhodecode.model.repo import RepoModel
11 from rhodecode.model.meta import Session
11 from rhodecode.model.meta import Session
12 from rhodecode.model.scm import ScmModel
12 from rhodecode.model.scm import ScmModel
13 from rhodecode.model.db import Repository
13
14
14 API_URL = '/_admin/api'
15 API_URL = '/_admin/api'
15
16
16
17
17 def _build_data(apikey, method, **kw):
18 def _build_data(apikey, method, **kw):
18 """
19 """
19 Builds API data with given random ID
20 Builds API data with given random ID
20
21
21 :param random_id:
22 :param random_id:
22 :type random_id:
23 :type random_id:
23 """
24 """
24 random_id = random.randrange(1, 9999)
25 random_id = random.randrange(1, 9999)
25 return random_id, json.dumps({
26 return random_id, json.dumps({
26 "id": random_id,
27 "id": random_id,
27 "api_key": apikey,
28 "api_key": apikey,
28 "method": method,
29 "method": method,
29 "args": kw
30 "args": kw
30 })
31 })
31
32
32 jsonify = lambda obj: json.loads(json.dumps(obj))
33 jsonify = lambda obj: json.loads(json.dumps(obj))
33
34
34
35
35 def crash(*args, **kwargs):
36 def crash(*args, **kwargs):
36 raise Exception('Total Crash !')
37 raise Exception('Total Crash !')
37
38
38
39
39 TEST_USERS_GROUP = 'test_users_group'
40 TEST_USERS_GROUP = 'test_users_group'
40
41
41
42
42 def make_users_group(name=TEST_USERS_GROUP):
43 def make_users_group(name=TEST_USERS_GROUP):
43 gr = UsersGroupModel().create(name=name)
44 gr = UsersGroupModel().create(name=name)
44 UsersGroupModel().add_user_to_group(users_group=gr,
45 UsersGroupModel().add_user_to_group(users_group=gr,
45 user=TEST_USER_ADMIN_LOGIN)
46 user=TEST_USER_ADMIN_LOGIN)
46 Session().commit()
47 Session().commit()
47 return gr
48 return gr
48
49
49
50
50 def destroy_users_group(name=TEST_USERS_GROUP):
51 def destroy_users_group(name=TEST_USERS_GROUP):
51 UsersGroupModel().delete(users_group=name, force=True)
52 UsersGroupModel().delete(users_group=name, force=True)
52 Session().commit()
53 Session().commit()
53
54
54
55
55 def create_repo(repo_name, repo_type):
56 def create_repo(repo_name, repo_type):
56 # create new repo
57 # create new repo
57 form_data = dict(repo_name=repo_name,
58 form_data = dict(repo_name=repo_name,
58 repo_name_full=repo_name,
59 repo_name_full=repo_name,
59 fork_name=None,
60 fork_name=None,
60 description='description %s' % repo_name,
61 description='description %s' % repo_name,
61 repo_group=None,
62 repo_group=None,
62 private=False,
63 private=False,
63 repo_type=repo_type,
64 repo_type=repo_type,
64 clone_uri=None,
65 clone_uri=None,
65 landing_rev='tip')
66 landing_rev='tip')
66 cur_user = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
67 cur_user = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
67 r = RepoModel().create(form_data, cur_user)
68 r = RepoModel().create(form_data, cur_user)
68 Session().commit()
69 Session().commit()
69 return r
70 return r
70
71
71
72
72 def create_fork(fork_name, fork_type, fork_of):
73 def create_fork(fork_name, fork_type, fork_of):
73 fork = RepoModel(Session())._get_repo(fork_of)
74 fork = RepoModel(Session())._get_repo(fork_of)
74 r = create_repo(fork_name, fork_type)
75 r = create_repo(fork_name, fork_type)
75 r.fork = fork
76 r.fork = fork
76 Session().add(r)
77 Session().add(r)
77 Session().commit()
78 Session().commit()
78 return r
79 return r
79
80
80
81
81 def destroy_repo(repo_name):
82 def destroy_repo(repo_name):
82 RepoModel().delete(repo_name)
83 RepoModel().delete(repo_name)
83 Session().commit()
84 Session().commit()
84
85
85
86
86 class BaseTestApi(object):
87 class BaseTestApi(object):
87 REPO = None
88 REPO = None
88 REPO_TYPE = None
89 REPO_TYPE = None
89
90
90 @classmethod
91 @classmethod
91 def setUpClass(self):
92 def setUpClass(self):
92 self.usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
93 self.usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
93 self.apikey = self.usr.api_key
94 self.apikey = self.usr.api_key
94 self.TEST_USER = UserModel().create_or_update(
95 self.TEST_USER = UserModel().create_or_update(
95 username='test-api',
96 username='test-api',
96 password='test',
97 password='test',
97 email='test@api.rhodecode.org',
98 email='test@api.rhodecode.org',
98 firstname='first',
99 firstname='first',
99 lastname='last'
100 lastname='last'
100 )
101 )
101 Session().commit()
102 Session().commit()
102 self.TEST_USER_LOGIN = self.TEST_USER.username
103 self.TEST_USER_LOGIN = self.TEST_USER.username
103
104
104 @classmethod
105 @classmethod
105 def teardownClass(self):
106 def teardownClass(self):
106 pass
107 pass
107
108
108 def setUp(self):
109 def setUp(self):
109 self.maxDiff = None
110 self.maxDiff = None
110 make_users_group()
111 make_users_group()
111
112
112 def tearDown(self):
113 def tearDown(self):
113 destroy_users_group()
114 destroy_users_group()
114
115
115 def _compare_ok(self, id_, expected, given):
116 def _compare_ok(self, id_, expected, given):
116 expected = jsonify({
117 expected = jsonify({
117 'id': id_,
118 'id': id_,
118 'error': None,
119 'error': None,
119 'result': expected
120 'result': expected
120 })
121 })
121 given = json.loads(given)
122 given = json.loads(given)
122 self.assertEqual(expected, given)
123 self.assertEqual(expected, given)
123
124
124 def _compare_error(self, id_, expected, given):
125 def _compare_error(self, id_, expected, given):
125 expected = jsonify({
126 expected = jsonify({
126 'id': id_,
127 'id': id_,
127 'error': expected,
128 'error': expected,
128 'result': None
129 'result': None
129 })
130 })
130 given = json.loads(given)
131 given = json.loads(given)
131 self.assertEqual(expected, given)
132 self.assertEqual(expected, given)
132
133
133 # def test_Optional(self):
134 # def test_Optional(self):
134 # from rhodecode.controllers.api.api import Optional
135 # from rhodecode.controllers.api.api import Optional
135 # option1 = Optional(None)
136 # option1 = Optional(None)
136 # self.assertEqual('<Optional:%s>' % None, repr(option1))
137 # self.assertEqual('<Optional:%s>' % None, repr(option1))
137 #
138 #
138 # self.assertEqual(1, Optional.extract(Optional(1)))
139 # self.assertEqual(1, Optional.extract(Optional(1)))
139 # self.assertEqual('trololo', Optional.extract('trololo'))
140 # self.assertEqual('trololo', Optional.extract('trololo'))
140
141
141 def test_api_wrong_key(self):
142 def test_api_wrong_key(self):
142 id_, params = _build_data('trololo', 'get_user')
143 id_, params = _build_data('trololo', 'get_user')
143 response = self.app.post(API_URL, content_type='application/json',
144 response = self.app.post(API_URL, content_type='application/json',
144 params=params)
145 params=params)
145
146
146 expected = 'Invalid API KEY'
147 expected = 'Invalid API KEY'
147 self._compare_error(id_, expected, given=response.body)
148 self._compare_error(id_, expected, given=response.body)
148
149
149 def test_api_missing_non_optional_param(self):
150 def test_api_missing_non_optional_param(self):
150 id_, params = _build_data(self.apikey, 'get_user')
151 id_, params = _build_data(self.apikey, 'get_user')
151 response = self.app.post(API_URL, content_type='application/json',
152 response = self.app.post(API_URL, content_type='application/json',
152 params=params)
153 params=params)
153
154
154 expected = 'Missing non optional `userid` arg in JSON DATA'
155 expected = 'Missing non optional `userid` arg in JSON DATA'
155 self._compare_error(id_, expected, given=response.body)
156 self._compare_error(id_, expected, given=response.body)
156
157
157 def test_api_get_users(self):
158 def test_api_get_users(self):
158 id_, params = _build_data(self.apikey, 'get_users',)
159 id_, params = _build_data(self.apikey, 'get_users',)
159 response = self.app.post(API_URL, content_type='application/json',
160 response = self.app.post(API_URL, content_type='application/json',
160 params=params)
161 params=params)
161 ret_all = []
162 ret_all = []
162 for usr in UserModel().get_all():
163 for usr in UserModel().get_all():
163 ret = usr.get_api_data()
164 ret = usr.get_api_data()
164 ret_all.append(jsonify(ret))
165 ret_all.append(jsonify(ret))
165 expected = ret_all
166 expected = ret_all
166 self._compare_ok(id_, expected, given=response.body)
167 self._compare_ok(id_, expected, given=response.body)
167
168
168 def test_api_get_user(self):
169 def test_api_get_user(self):
169 id_, params = _build_data(self.apikey, 'get_user',
170 id_, params = _build_data(self.apikey, 'get_user',
170 userid=TEST_USER_ADMIN_LOGIN)
171 userid=TEST_USER_ADMIN_LOGIN)
171 response = self.app.post(API_URL, content_type='application/json',
172 response = self.app.post(API_URL, content_type='application/json',
172 params=params)
173 params=params)
173
174
174 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
175 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
175 ret = usr.get_api_data()
176 ret = usr.get_api_data()
176 ret['permissions'] = AuthUser(usr.user_id).permissions
177 ret['permissions'] = AuthUser(usr.user_id).permissions
177
178
178 expected = ret
179 expected = ret
179 self._compare_ok(id_, expected, given=response.body)
180 self._compare_ok(id_, expected, given=response.body)
180
181
181 def test_api_get_user_that_does_not_exist(self):
182 def test_api_get_user_that_does_not_exist(self):
182 id_, params = _build_data(self.apikey, 'get_user',
183 id_, params = _build_data(self.apikey, 'get_user',
183 userid='trololo')
184 userid='trololo')
184 response = self.app.post(API_URL, content_type='application/json',
185 response = self.app.post(API_URL, content_type='application/json',
185 params=params)
186 params=params)
186
187
187 expected = "user `%s` does not exist" % 'trololo'
188 expected = "user `%s` does not exist" % 'trololo'
188 self._compare_error(id_, expected, given=response.body)
189 self._compare_error(id_, expected, given=response.body)
189
190
190 def test_api_pull(self):
191 def test_api_pull(self):
191 #TODO: issues with rhodecode_extras here.. not sure why !
192 #TODO: issues with rhodecode_extras here.. not sure why !
192 pass
193 pass
193
194
194 # repo_name = 'test_pull'
195 # repo_name = 'test_pull'
195 # r = create_repo(repo_name, self.REPO_TYPE)
196 # r = create_repo(repo_name, self.REPO_TYPE)
196 # r.clone_uri = TEST_self.REPO
197 # r.clone_uri = TEST_self.REPO
197 # Session.add(r)
198 # Session.add(r)
198 # Session.commit()
199 # Session.commit()
199 #
200 #
200 # id_, params = _build_data(self.apikey, 'pull',
201 # id_, params = _build_data(self.apikey, 'pull',
201 # repoid=repo_name,)
202 # repoid=repo_name,)
202 # response = self.app.post(API_URL, content_type='application/json',
203 # response = self.app.post(API_URL, content_type='application/json',
203 # params=params)
204 # params=params)
204 #
205 #
205 # expected = 'Pulled from `%s`' % repo_name
206 # expected = 'Pulled from `%s`' % repo_name
206 # self._compare_ok(id_, expected, given=response.body)
207 # self._compare_ok(id_, expected, given=response.body)
207 #
208 #
208 # destroy_repo(repo_name)
209 # destroy_repo(repo_name)
209
210
210 def test_api_pull_error(self):
211 def test_api_pull_error(self):
211 id_, params = _build_data(self.apikey, 'pull',
212 id_, params = _build_data(self.apikey, 'pull',
212 repoid=self.REPO,)
213 repoid=self.REPO,)
213 response = self.app.post(API_URL, content_type='application/json',
214 response = self.app.post(API_URL, content_type='application/json',
214 params=params)
215 params=params)
215
216
216 expected = 'Unable to pull changes from `%s`' % self.REPO
217 expected = 'Unable to pull changes from `%s`' % self.REPO
217 self._compare_error(id_, expected, given=response.body)
218 self._compare_error(id_, expected, given=response.body)
218
219
219 def test_api_rescan_repos(self):
220 def test_api_rescan_repos(self):
220 id_, params = _build_data(self.apikey, 'rescan_repos')
221 id_, params = _build_data(self.apikey, 'rescan_repos')
221 response = self.app.post(API_URL, content_type='application/json',
222 response = self.app.post(API_URL, content_type='application/json',
222 params=params)
223 params=params)
223
224
224 expected = {'added': [], 'removed': []}
225 expected = {'added': [], 'removed': []}
225 self._compare_ok(id_, expected, given=response.body)
226 self._compare_ok(id_, expected, given=response.body)
226
227
227 @mock.patch.object(ScmModel, 'repo_scan', crash)
228 @mock.patch.object(ScmModel, 'repo_scan', crash)
228 def test_api_rescann_error(self):
229 def test_api_rescann_error(self):
229 id_, params = _build_data(self.apikey, 'rescan_repos',)
230 id_, params = _build_data(self.apikey, 'rescan_repos',)
230 response = self.app.post(API_URL, content_type='application/json',
231 response = self.app.post(API_URL, content_type='application/json',
231 params=params)
232 params=params)
232
233
233 expected = 'Unable to rescan repositories'
234 expected = 'Error occurred during rescan repositories action'
235 self._compare_error(id_, expected, given=response.body)
236
237 def test_api_lock_repo_lock_aquire(self):
238 id_, params = _build_data(self.apikey, 'lock',
239 userid=TEST_USER_ADMIN_LOGIN,
240 repoid=self.REPO,
241 locked=True)
242 response = self.app.post(API_URL, content_type='application/json',
243 params=params)
244 expected = ('User `%s` set lock state for repo `%s` to `%s`'
245 % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
246 self._compare_ok(id_, expected, given=response.body)
247
248 def test_api_lock_repo_lock_release(self):
249 id_, params = _build_data(self.apikey, 'lock',
250 userid=TEST_USER_ADMIN_LOGIN,
251 repoid=self.REPO,
252 locked=False)
253 response = self.app.post(API_URL, content_type='application/json',
254 params=params)
255 expected = ('User `%s` set lock state for repo `%s` to `%s`'
256 % (TEST_USER_ADMIN_LOGIN, self.REPO, False))
257 self._compare_ok(id_, expected, given=response.body)
258
259 @mock.patch.object(Repository, 'lock', crash)
260 def test_api_lock_error(self):
261 id_, params = _build_data(self.apikey, 'lock',
262 userid=TEST_USER_ADMIN_LOGIN,
263 repoid=self.REPO,
264 locked=True)
265 response = self.app.post(API_URL, content_type='application/json',
266 params=params)
267
268 expected = 'Error occurred locking repository `%s`' % self.REPO
234 self._compare_error(id_, expected, given=response.body)
269 self._compare_error(id_, expected, given=response.body)
235
270
236 def test_api_create_existing_user(self):
271 def test_api_create_existing_user(self):
237 id_, params = _build_data(self.apikey, 'create_user',
272 id_, params = _build_data(self.apikey, 'create_user',
238 username=TEST_USER_ADMIN_LOGIN,
273 username=TEST_USER_ADMIN_LOGIN,
239 email='test@foo.com',
274 email='test@foo.com',
240 password='trololo')
275 password='trololo')
241 response = self.app.post(API_URL, content_type='application/json',
276 response = self.app.post(API_URL, content_type='application/json',
242 params=params)
277 params=params)
243
278
244 expected = "user `%s` already exist" % TEST_USER_ADMIN_LOGIN
279 expected = "user `%s` already exist" % TEST_USER_ADMIN_LOGIN
245 self._compare_error(id_, expected, given=response.body)
280 self._compare_error(id_, expected, given=response.body)
246
281
247 def test_api_create_user_with_existing_email(self):
282 def test_api_create_user_with_existing_email(self):
248 id_, params = _build_data(self.apikey, 'create_user',
283 id_, params = _build_data(self.apikey, 'create_user',
249 username=TEST_USER_ADMIN_LOGIN + 'new',
284 username=TEST_USER_ADMIN_LOGIN + 'new',
250 email=TEST_USER_REGULAR_EMAIL,
285 email=TEST_USER_REGULAR_EMAIL,
251 password='trololo')
286 password='trololo')
252 response = self.app.post(API_URL, content_type='application/json',
287 response = self.app.post(API_URL, content_type='application/json',
253 params=params)
288 params=params)
254
289
255 expected = "email `%s` already exist" % TEST_USER_REGULAR_EMAIL
290 expected = "email `%s` already exist" % TEST_USER_REGULAR_EMAIL
256 self._compare_error(id_, expected, given=response.body)
291 self._compare_error(id_, expected, given=response.body)
257
292
258 def test_api_create_user(self):
293 def test_api_create_user(self):
259 username = 'test_new_api_user'
294 username = 'test_new_api_user'
260 email = username + "@foo.com"
295 email = username + "@foo.com"
261
296
262 id_, params = _build_data(self.apikey, 'create_user',
297 id_, params = _build_data(self.apikey, 'create_user',
263 username=username,
298 username=username,
264 email=email,
299 email=email,
265 password='trololo')
300 password='trololo')
266 response = self.app.post(API_URL, content_type='application/json',
301 response = self.app.post(API_URL, content_type='application/json',
267 params=params)
302 params=params)
268
303
269 usr = UserModel().get_by_username(username)
304 usr = UserModel().get_by_username(username)
270 ret = dict(
305 ret = dict(
271 msg='created new user `%s`' % username,
306 msg='created new user `%s`' % username,
272 user=jsonify(usr.get_api_data())
307 user=jsonify(usr.get_api_data())
273 )
308 )
274
309
275 expected = ret
310 expected = ret
276 self._compare_ok(id_, expected, given=response.body)
311 self._compare_ok(id_, expected, given=response.body)
277
312
278 UserModel().delete(usr.user_id)
313 UserModel().delete(usr.user_id)
279 self.Session().commit()
314 self.Session().commit()
280
315
281 @mock.patch.object(UserModel, 'create_or_update', crash)
316 @mock.patch.object(UserModel, 'create_or_update', crash)
282 def test_api_create_user_when_exception_happened(self):
317 def test_api_create_user_when_exception_happened(self):
283
318
284 username = 'test_new_api_user'
319 username = 'test_new_api_user'
285 email = username + "@foo.com"
320 email = username + "@foo.com"
286
321
287 id_, params = _build_data(self.apikey, 'create_user',
322 id_, params = _build_data(self.apikey, 'create_user',
288 username=username,
323 username=username,
289 email=email,
324 email=email,
290 password='trololo')
325 password='trololo')
291 response = self.app.post(API_URL, content_type='application/json',
326 response = self.app.post(API_URL, content_type='application/json',
292 params=params)
327 params=params)
293 expected = 'failed to create user `%s`' % username
328 expected = 'failed to create user `%s`' % username
294 self._compare_error(id_, expected, given=response.body)
329 self._compare_error(id_, expected, given=response.body)
295
330
296 def test_api_delete_user(self):
331 def test_api_delete_user(self):
297 usr = UserModel().create_or_update(username=u'test_user',
332 usr = UserModel().create_or_update(username=u'test_user',
298 password=u'qweqwe',
333 password=u'qweqwe',
299 email=u'u232@rhodecode.org',
334 email=u'u232@rhodecode.org',
300 firstname=u'u1', lastname=u'u1')
335 firstname=u'u1', lastname=u'u1')
301 self.Session().commit()
336 self.Session().commit()
302 username = usr.username
337 username = usr.username
303 email = usr.email
338 email = usr.email
304 usr_id = usr.user_id
339 usr_id = usr.user_id
305 ## DELETE THIS USER NOW
340 ## DELETE THIS USER NOW
306
341
307 id_, params = _build_data(self.apikey, 'delete_user',
342 id_, params = _build_data(self.apikey, 'delete_user',
308 userid=username,)
343 userid=username,)
309 response = self.app.post(API_URL, content_type='application/json',
344 response = self.app.post(API_URL, content_type='application/json',
310 params=params)
345 params=params)
311
346
312 ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username),
347 ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username),
313 'user': None}
348 'user': None}
314 expected = ret
349 expected = ret
315 self._compare_ok(id_, expected, given=response.body)
350 self._compare_ok(id_, expected, given=response.body)
316
351
317 @mock.patch.object(UserModel, 'delete', crash)
352 @mock.patch.object(UserModel, 'delete', crash)
318 def test_api_delete_user_when_exception_happened(self):
353 def test_api_delete_user_when_exception_happened(self):
319 usr = UserModel().create_or_update(username=u'test_user',
354 usr = UserModel().create_or_update(username=u'test_user',
320 password=u'qweqwe',
355 password=u'qweqwe',
321 email=u'u232@rhodecode.org',
356 email=u'u232@rhodecode.org',
322 firstname=u'u1', lastname=u'u1')
357 firstname=u'u1', lastname=u'u1')
323 self.Session().commit()
358 self.Session().commit()
324 username = usr.username
359 username = usr.username
325
360
326 id_, params = _build_data(self.apikey, 'delete_user',
361 id_, params = _build_data(self.apikey, 'delete_user',
327 userid=username,)
362 userid=username,)
328 response = self.app.post(API_URL, content_type='application/json',
363 response = self.app.post(API_URL, content_type='application/json',
329 params=params)
364 params=params)
330 ret = 'failed to delete ID:%s %s' % (usr.user_id,
365 ret = 'failed to delete ID:%s %s' % (usr.user_id,
331 usr.username)
366 usr.username)
332 expected = ret
367 expected = ret
333 self._compare_error(id_, expected, given=response.body)
368 self._compare_error(id_, expected, given=response.body)
334
369
335 @parameterized.expand([('firstname', 'new_username'),
370 @parameterized.expand([('firstname', 'new_username'),
336 ('lastname', 'new_username'),
371 ('lastname', 'new_username'),
337 ('email', 'new_username'),
372 ('email', 'new_username'),
338 ('admin', True),
373 ('admin', True),
339 ('admin', False),
374 ('admin', False),
340 ('ldap_dn', 'test'),
375 ('ldap_dn', 'test'),
341 ('ldap_dn', None),
376 ('ldap_dn', None),
342 ('active', False),
377 ('active', False),
343 ('active', True),
378 ('active', True),
344 ('password', 'newpass')
379 ('password', 'newpass')
345 ])
380 ])
346 def test_api_update_user(self, name, expected):
381 def test_api_update_user(self, name, expected):
347 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
382 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
348 kw = {name: expected,
383 kw = {name: expected,
349 'userid': usr.user_id}
384 'userid': usr.user_id}
350 id_, params = _build_data(self.apikey, 'update_user', **kw)
385 id_, params = _build_data(self.apikey, 'update_user', **kw)
351 response = self.app.post(API_URL, content_type='application/json',
386 response = self.app.post(API_URL, content_type='application/json',
352 params=params)
387 params=params)
353
388
354 ret = {
389 ret = {
355 'msg': 'updated user ID:%s %s' % (usr.user_id, self.TEST_USER_LOGIN),
390 'msg': 'updated user ID:%s %s' % (usr.user_id, self.TEST_USER_LOGIN),
356 'user': jsonify(UserModel()\
391 'user': jsonify(UserModel()\
357 .get_by_username(self.TEST_USER_LOGIN)\
392 .get_by_username(self.TEST_USER_LOGIN)\
358 .get_api_data())
393 .get_api_data())
359 }
394 }
360
395
361 expected = ret
396 expected = ret
362 self._compare_ok(id_, expected, given=response.body)
397 self._compare_ok(id_, expected, given=response.body)
363
398
364 def test_api_update_user_no_changed_params(self):
399 def test_api_update_user_no_changed_params(self):
365 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
400 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
366 ret = jsonify(usr.get_api_data())
401 ret = jsonify(usr.get_api_data())
367 id_, params = _build_data(self.apikey, 'update_user',
402 id_, params = _build_data(self.apikey, 'update_user',
368 userid=TEST_USER_ADMIN_LOGIN)
403 userid=TEST_USER_ADMIN_LOGIN)
369
404
370 response = self.app.post(API_URL, content_type='application/json',
405 response = self.app.post(API_URL, content_type='application/json',
371 params=params)
406 params=params)
372 ret = {
407 ret = {
373 'msg': 'updated user ID:%s %s' % (usr.user_id, TEST_USER_ADMIN_LOGIN),
408 'msg': 'updated user ID:%s %s' % (usr.user_id, TEST_USER_ADMIN_LOGIN),
374 'user': ret
409 'user': ret
375 }
410 }
376 expected = ret
411 expected = ret
377 self._compare_ok(id_, expected, given=response.body)
412 self._compare_ok(id_, expected, given=response.body)
378
413
379 def test_api_update_user_by_user_id(self):
414 def test_api_update_user_by_user_id(self):
380 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
415 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
381 ret = jsonify(usr.get_api_data())
416 ret = jsonify(usr.get_api_data())
382 id_, params = _build_data(self.apikey, 'update_user',
417 id_, params = _build_data(self.apikey, 'update_user',
383 userid=usr.user_id)
418 userid=usr.user_id)
384
419
385 response = self.app.post(API_URL, content_type='application/json',
420 response = self.app.post(API_URL, content_type='application/json',
386 params=params)
421 params=params)
387 ret = {
422 ret = {
388 'msg': 'updated user ID:%s %s' % (usr.user_id, TEST_USER_ADMIN_LOGIN),
423 'msg': 'updated user ID:%s %s' % (usr.user_id, TEST_USER_ADMIN_LOGIN),
389 'user': ret
424 'user': ret
390 }
425 }
391 expected = ret
426 expected = ret
392 self._compare_ok(id_, expected, given=response.body)
427 self._compare_ok(id_, expected, given=response.body)
393
428
394 @mock.patch.object(UserModel, 'update_user', crash)
429 @mock.patch.object(UserModel, 'update_user', crash)
395 def test_api_update_user_when_exception_happens(self):
430 def test_api_update_user_when_exception_happens(self):
396 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
431 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
397 ret = jsonify(usr.get_api_data())
432 ret = jsonify(usr.get_api_data())
398 id_, params = _build_data(self.apikey, 'update_user',
433 id_, params = _build_data(self.apikey, 'update_user',
399 userid=usr.user_id)
434 userid=usr.user_id)
400
435
401 response = self.app.post(API_URL, content_type='application/json',
436 response = self.app.post(API_URL, content_type='application/json',
402 params=params)
437 params=params)
403 ret = 'failed to update user `%s`' % usr.user_id
438 ret = 'failed to update user `%s`' % usr.user_id
404
439
405 expected = ret
440 expected = ret
406 self._compare_error(id_, expected, given=response.body)
441 self._compare_error(id_, expected, given=response.body)
407
442
408 def test_api_get_repo(self):
443 def test_api_get_repo(self):
409 new_group = 'some_new_group'
444 new_group = 'some_new_group'
410 make_users_group(new_group)
445 make_users_group(new_group)
411 RepoModel().grant_users_group_permission(repo=self.REPO,
446 RepoModel().grant_users_group_permission(repo=self.REPO,
412 group_name=new_group,
447 group_name=new_group,
413 perm='repository.read')
448 perm='repository.read')
414 self.Session().commit()
449 self.Session().commit()
415 id_, params = _build_data(self.apikey, 'get_repo',
450 id_, params = _build_data(self.apikey, 'get_repo',
416 repoid=self.REPO)
451 repoid=self.REPO)
417 response = self.app.post(API_URL, content_type='application/json',
452 response = self.app.post(API_URL, content_type='application/json',
418 params=params)
453 params=params)
419
454
420 repo = RepoModel().get_by_repo_name(self.REPO)
455 repo = RepoModel().get_by_repo_name(self.REPO)
421 ret = repo.get_api_data()
456 ret = repo.get_api_data()
422
457
423 members = []
458 members = []
424 for user in repo.repo_to_perm:
459 for user in repo.repo_to_perm:
425 perm = user.permission.permission_name
460 perm = user.permission.permission_name
426 user = user.user
461 user = user.user
427 user_data = user.get_api_data()
462 user_data = user.get_api_data()
428 user_data['type'] = "user"
463 user_data['type'] = "user"
429 user_data['permission'] = perm
464 user_data['permission'] = perm
430 members.append(user_data)
465 members.append(user_data)
431
466
432 for users_group in repo.users_group_to_perm:
467 for users_group in repo.users_group_to_perm:
433 perm = users_group.permission.permission_name
468 perm = users_group.permission.permission_name
434 users_group = users_group.users_group
469 users_group = users_group.users_group
435 users_group_data = users_group.get_api_data()
470 users_group_data = users_group.get_api_data()
436 users_group_data['type'] = "users_group"
471 users_group_data['type'] = "users_group"
437 users_group_data['permission'] = perm
472 users_group_data['permission'] = perm
438 members.append(users_group_data)
473 members.append(users_group_data)
439
474
440 ret['members'] = members
475 ret['members'] = members
441
476
442 expected = ret
477 expected = ret
443 self._compare_ok(id_, expected, given=response.body)
478 self._compare_ok(id_, expected, given=response.body)
444 destroy_users_group(new_group)
479 destroy_users_group(new_group)
445
480
446 def test_api_get_repo_that_doesn_not_exist(self):
481 def test_api_get_repo_that_doesn_not_exist(self):
447 id_, params = _build_data(self.apikey, 'get_repo',
482 id_, params = _build_data(self.apikey, 'get_repo',
448 repoid='no-such-repo')
483 repoid='no-such-repo')
449 response = self.app.post(API_URL, content_type='application/json',
484 response = self.app.post(API_URL, content_type='application/json',
450 params=params)
485 params=params)
451
486
452 ret = 'repository `%s` does not exist' % 'no-such-repo'
487 ret = 'repository `%s` does not exist' % 'no-such-repo'
453 expected = ret
488 expected = ret
454 self._compare_error(id_, expected, given=response.body)
489 self._compare_error(id_, expected, given=response.body)
455
490
456 def test_api_get_repos(self):
491 def test_api_get_repos(self):
457 id_, params = _build_data(self.apikey, 'get_repos')
492 id_, params = _build_data(self.apikey, 'get_repos')
458 response = self.app.post(API_URL, content_type='application/json',
493 response = self.app.post(API_URL, content_type='application/json',
459 params=params)
494 params=params)
460
495
461 result = []
496 result = []
462 for repo in RepoModel().get_all():
497 for repo in RepoModel().get_all():
463 result.append(repo.get_api_data())
498 result.append(repo.get_api_data())
464 ret = jsonify(result)
499 ret = jsonify(result)
465
500
466 expected = ret
501 expected = ret
467 self._compare_ok(id_, expected, given=response.body)
502 self._compare_ok(id_, expected, given=response.body)
468
503
469 @parameterized.expand([('all', 'all'),
504 @parameterized.expand([('all', 'all'),
470 ('dirs', 'dirs'),
505 ('dirs', 'dirs'),
471 ('files', 'files'), ])
506 ('files', 'files'), ])
472 def test_api_get_repo_nodes(self, name, ret_type):
507 def test_api_get_repo_nodes(self, name, ret_type):
473 rev = 'tip'
508 rev = 'tip'
474 path = '/'
509 path = '/'
475 id_, params = _build_data(self.apikey, 'get_repo_nodes',
510 id_, params = _build_data(self.apikey, 'get_repo_nodes',
476 repoid=self.REPO, revision=rev,
511 repoid=self.REPO, revision=rev,
477 root_path=path,
512 root_path=path,
478 ret_type=ret_type)
513 ret_type=ret_type)
479 response = self.app.post(API_URL, content_type='application/json',
514 response = self.app.post(API_URL, content_type='application/json',
480 params=params)
515 params=params)
481
516
482 # we don't the actual return types here since it's tested somewhere
517 # we don't the actual return types here since it's tested somewhere
483 # else
518 # else
484 expected = json.loads(response.body)['result']
519 expected = json.loads(response.body)['result']
485 self._compare_ok(id_, expected, given=response.body)
520 self._compare_ok(id_, expected, given=response.body)
486
521
487 def test_api_get_repo_nodes_bad_revisions(self):
522 def test_api_get_repo_nodes_bad_revisions(self):
488 rev = 'i-dont-exist'
523 rev = 'i-dont-exist'
489 path = '/'
524 path = '/'
490 id_, params = _build_data(self.apikey, 'get_repo_nodes',
525 id_, params = _build_data(self.apikey, 'get_repo_nodes',
491 repoid=self.REPO, revision=rev,
526 repoid=self.REPO, revision=rev,
492 root_path=path,)
527 root_path=path,)
493 response = self.app.post(API_URL, content_type='application/json',
528 response = self.app.post(API_URL, content_type='application/json',
494 params=params)
529 params=params)
495
530
496 expected = 'failed to get repo: `%s` nodes' % self.REPO
531 expected = 'failed to get repo: `%s` nodes' % self.REPO
497 self._compare_error(id_, expected, given=response.body)
532 self._compare_error(id_, expected, given=response.body)
498
533
499 def test_api_get_repo_nodes_bad_path(self):
534 def test_api_get_repo_nodes_bad_path(self):
500 rev = 'tip'
535 rev = 'tip'
501 path = '/idontexits'
536 path = '/idontexits'
502 id_, params = _build_data(self.apikey, 'get_repo_nodes',
537 id_, params = _build_data(self.apikey, 'get_repo_nodes',
503 repoid=self.REPO, revision=rev,
538 repoid=self.REPO, revision=rev,
504 root_path=path,)
539 root_path=path,)
505 response = self.app.post(API_URL, content_type='application/json',
540 response = self.app.post(API_URL, content_type='application/json',
506 params=params)
541 params=params)
507
542
508 expected = 'failed to get repo: `%s` nodes' % self.REPO
543 expected = 'failed to get repo: `%s` nodes' % self.REPO
509 self._compare_error(id_, expected, given=response.body)
544 self._compare_error(id_, expected, given=response.body)
510
545
511 def test_api_get_repo_nodes_bad_ret_type(self):
546 def test_api_get_repo_nodes_bad_ret_type(self):
512 rev = 'tip'
547 rev = 'tip'
513 path = '/'
548 path = '/'
514 ret_type = 'error'
549 ret_type = 'error'
515 id_, params = _build_data(self.apikey, 'get_repo_nodes',
550 id_, params = _build_data(self.apikey, 'get_repo_nodes',
516 repoid=self.REPO, revision=rev,
551 repoid=self.REPO, revision=rev,
517 root_path=path,
552 root_path=path,
518 ret_type=ret_type)
553 ret_type=ret_type)
519 response = self.app.post(API_URL, content_type='application/json',
554 response = self.app.post(API_URL, content_type='application/json',
520 params=params)
555 params=params)
521
556
522 expected = 'ret_type must be one of %s' % (['files', 'dirs', 'all'])
557 expected = 'ret_type must be one of %s' % (['files', 'dirs', 'all'])
523 self._compare_error(id_, expected, given=response.body)
558 self._compare_error(id_, expected, given=response.body)
524
559
525 def test_api_create_repo(self):
560 def test_api_create_repo(self):
526 repo_name = 'api-repo'
561 repo_name = 'api-repo'
527 id_, params = _build_data(self.apikey, 'create_repo',
562 id_, params = _build_data(self.apikey, 'create_repo',
528 repo_name=repo_name,
563 repo_name=repo_name,
529 owner=TEST_USER_ADMIN_LOGIN,
564 owner=TEST_USER_ADMIN_LOGIN,
530 repo_type='hg',
565 repo_type='hg',
531 )
566 )
532 response = self.app.post(API_URL, content_type='application/json',
567 response = self.app.post(API_URL, content_type='application/json',
533 params=params)
568 params=params)
534
569
535 repo = RepoModel().get_by_repo_name(repo_name)
570 repo = RepoModel().get_by_repo_name(repo_name)
536 ret = {
571 ret = {
537 'msg': 'Created new repository `%s`' % repo_name,
572 'msg': 'Created new repository `%s`' % repo_name,
538 'repo': jsonify(repo.get_api_data())
573 'repo': jsonify(repo.get_api_data())
539 }
574 }
540 expected = ret
575 expected = ret
541 self._compare_ok(id_, expected, given=response.body)
576 self._compare_ok(id_, expected, given=response.body)
542 destroy_repo(repo_name)
577 destroy_repo(repo_name)
543
578
544 def test_api_create_repo_unknown_owner(self):
579 def test_api_create_repo_unknown_owner(self):
545 repo_name = 'api-repo'
580 repo_name = 'api-repo'
546 owner = 'i-dont-exist'
581 owner = 'i-dont-exist'
547 id_, params = _build_data(self.apikey, 'create_repo',
582 id_, params = _build_data(self.apikey, 'create_repo',
548 repo_name=repo_name,
583 repo_name=repo_name,
549 owner=owner,
584 owner=owner,
550 repo_type='hg',
585 repo_type='hg',
551 )
586 )
552 response = self.app.post(API_URL, content_type='application/json',
587 response = self.app.post(API_URL, content_type='application/json',
553 params=params)
588 params=params)
554 expected = 'user `%s` does not exist' % owner
589 expected = 'user `%s` does not exist' % owner
555 self._compare_error(id_, expected, given=response.body)
590 self._compare_error(id_, expected, given=response.body)
556
591
557 def test_api_create_repo_exists(self):
592 def test_api_create_repo_exists(self):
558 repo_name = self.REPO
593 repo_name = self.REPO
559 id_, params = _build_data(self.apikey, 'create_repo',
594 id_, params = _build_data(self.apikey, 'create_repo',
560 repo_name=repo_name,
595 repo_name=repo_name,
561 owner=TEST_USER_ADMIN_LOGIN,
596 owner=TEST_USER_ADMIN_LOGIN,
562 repo_type='hg',
597 repo_type='hg',
563 )
598 )
564 response = self.app.post(API_URL, content_type='application/json',
599 response = self.app.post(API_URL, content_type='application/json',
565 params=params)
600 params=params)
566 expected = "repo `%s` already exist" % repo_name
601 expected = "repo `%s` already exist" % repo_name
567 self._compare_error(id_, expected, given=response.body)
602 self._compare_error(id_, expected, given=response.body)
568
603
569 @mock.patch.object(RepoModel, 'create_repo', crash)
604 @mock.patch.object(RepoModel, 'create_repo', crash)
570 def test_api_create_repo_exception_occurred(self):
605 def test_api_create_repo_exception_occurred(self):
571 repo_name = 'api-repo'
606 repo_name = 'api-repo'
572 id_, params = _build_data(self.apikey, 'create_repo',
607 id_, params = _build_data(self.apikey, 'create_repo',
573 repo_name=repo_name,
608 repo_name=repo_name,
574 owner=TEST_USER_ADMIN_LOGIN,
609 owner=TEST_USER_ADMIN_LOGIN,
575 repo_type='hg',
610 repo_type='hg',
576 )
611 )
577 response = self.app.post(API_URL, content_type='application/json',
612 response = self.app.post(API_URL, content_type='application/json',
578 params=params)
613 params=params)
579 expected = 'failed to create repository `%s`' % repo_name
614 expected = 'failed to create repository `%s`' % repo_name
580 self._compare_error(id_, expected, given=response.body)
615 self._compare_error(id_, expected, given=response.body)
581
616
582 def test_api_delete_repo(self):
617 def test_api_delete_repo(self):
583 repo_name = 'api_delete_me'
618 repo_name = 'api_delete_me'
584 create_repo(repo_name, self.REPO_TYPE)
619 create_repo(repo_name, self.REPO_TYPE)
585
620
586 id_, params = _build_data(self.apikey, 'delete_repo',
621 id_, params = _build_data(self.apikey, 'delete_repo',
587 repoid=repo_name,)
622 repoid=repo_name,)
588 response = self.app.post(API_URL, content_type='application/json',
623 response = self.app.post(API_URL, content_type='application/json',
589 params=params)
624 params=params)
590
625
591 ret = {
626 ret = {
592 'msg': 'Deleted repository `%s`' % repo_name,
627 'msg': 'Deleted repository `%s`' % repo_name,
593 'success': True
628 'success': True
594 }
629 }
595 expected = ret
630 expected = ret
596 self._compare_ok(id_, expected, given=response.body)
631 self._compare_ok(id_, expected, given=response.body)
597
632
598 def test_api_delete_repo_exception_occurred(self):
633 def test_api_delete_repo_exception_occurred(self):
599 repo_name = 'api_delete_me'
634 repo_name = 'api_delete_me'
600 create_repo(repo_name, self.REPO_TYPE)
635 create_repo(repo_name, self.REPO_TYPE)
601 try:
636 try:
602 with mock.patch.object(RepoModel, 'delete', crash):
637 with mock.patch.object(RepoModel, 'delete', crash):
603 id_, params = _build_data(self.apikey, 'delete_repo',
638 id_, params = _build_data(self.apikey, 'delete_repo',
604 repoid=repo_name,)
639 repoid=repo_name,)
605 response = self.app.post(API_URL, content_type='application/json',
640 response = self.app.post(API_URL, content_type='application/json',
606 params=params)
641 params=params)
607
642
608 expected = 'failed to delete repository `%s`' % repo_name
643 expected = 'failed to delete repository `%s`' % repo_name
609 self._compare_error(id_, expected, given=response.body)
644 self._compare_error(id_, expected, given=response.body)
610 finally:
645 finally:
611 destroy_repo(repo_name)
646 destroy_repo(repo_name)
612
647
613 def test_api_fork_repo(self):
648 def test_api_fork_repo(self):
614 fork_name = 'api-repo-fork'
649 fork_name = 'api-repo-fork'
615 id_, params = _build_data(self.apikey, 'fork_repo',
650 id_, params = _build_data(self.apikey, 'fork_repo',
616 repoid=self.REPO,
651 repoid=self.REPO,
617 fork_name=fork_name,
652 fork_name=fork_name,
618 owner=TEST_USER_ADMIN_LOGIN,
653 owner=TEST_USER_ADMIN_LOGIN,
619 )
654 )
620 response = self.app.post(API_URL, content_type='application/json',
655 response = self.app.post(API_URL, content_type='application/json',
621 params=params)
656 params=params)
622
657
623 ret = {
658 ret = {
624 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
659 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
625 fork_name),
660 fork_name),
626 'success': True
661 'success': True
627 }
662 }
628 expected = ret
663 expected = ret
629 self._compare_ok(id_, expected, given=response.body)
664 self._compare_ok(id_, expected, given=response.body)
630 destroy_repo(fork_name)
665 destroy_repo(fork_name)
631
666
632 def test_api_fork_repo_unknown_owner(self):
667 def test_api_fork_repo_unknown_owner(self):
633 fork_name = 'api-repo-fork'
668 fork_name = 'api-repo-fork'
634 owner = 'i-dont-exist'
669 owner = 'i-dont-exist'
635 id_, params = _build_data(self.apikey, 'fork_repo',
670 id_, params = _build_data(self.apikey, 'fork_repo',
636 repoid=self.REPO,
671 repoid=self.REPO,
637 fork_name=fork_name,
672 fork_name=fork_name,
638 owner=owner,
673 owner=owner,
639 )
674 )
640 response = self.app.post(API_URL, content_type='application/json',
675 response = self.app.post(API_URL, content_type='application/json',
641 params=params)
676 params=params)
642 expected = 'user `%s` does not exist' % owner
677 expected = 'user `%s` does not exist' % owner
643 self._compare_error(id_, expected, given=response.body)
678 self._compare_error(id_, expected, given=response.body)
644
679
645 def test_api_fork_repo_fork_exists(self):
680 def test_api_fork_repo_fork_exists(self):
646 fork_name = 'api-repo-fork'
681 fork_name = 'api-repo-fork'
647 create_fork(fork_name, self.REPO_TYPE, self.REPO)
682 create_fork(fork_name, self.REPO_TYPE, self.REPO)
648
683
649 try:
684 try:
650 fork_name = 'api-repo-fork'
685 fork_name = 'api-repo-fork'
651
686
652 id_, params = _build_data(self.apikey, 'fork_repo',
687 id_, params = _build_data(self.apikey, 'fork_repo',
653 repoid=self.REPO,
688 repoid=self.REPO,
654 fork_name=fork_name,
689 fork_name=fork_name,
655 owner=TEST_USER_ADMIN_LOGIN,
690 owner=TEST_USER_ADMIN_LOGIN,
656 )
691 )
657 response = self.app.post(API_URL, content_type='application/json',
692 response = self.app.post(API_URL, content_type='application/json',
658 params=params)
693 params=params)
659
694
660 expected = "fork `%s` already exist" % fork_name
695 expected = "fork `%s` already exist" % fork_name
661 self._compare_error(id_, expected, given=response.body)
696 self._compare_error(id_, expected, given=response.body)
662 finally:
697 finally:
663 destroy_repo(fork_name)
698 destroy_repo(fork_name)
664
699
665 def test_api_fork_repo_repo_exists(self):
700 def test_api_fork_repo_repo_exists(self):
666 fork_name = self.REPO
701 fork_name = self.REPO
667
702
668 id_, params = _build_data(self.apikey, 'fork_repo',
703 id_, params = _build_data(self.apikey, 'fork_repo',
669 repoid=self.REPO,
704 repoid=self.REPO,
670 fork_name=fork_name,
705 fork_name=fork_name,
671 owner=TEST_USER_ADMIN_LOGIN,
706 owner=TEST_USER_ADMIN_LOGIN,
672 )
707 )
673 response = self.app.post(API_URL, content_type='application/json',
708 response = self.app.post(API_URL, content_type='application/json',
674 params=params)
709 params=params)
675
710
676 expected = "repo `%s` already exist" % fork_name
711 expected = "repo `%s` already exist" % fork_name
677 self._compare_error(id_, expected, given=response.body)
712 self._compare_error(id_, expected, given=response.body)
678
713
679 @mock.patch.object(RepoModel, 'create_fork', crash)
714 @mock.patch.object(RepoModel, 'create_fork', crash)
680 def test_api_fork_repo_exception_occurred(self):
715 def test_api_fork_repo_exception_occurred(self):
681 fork_name = 'api-repo-fork'
716 fork_name = 'api-repo-fork'
682 id_, params = _build_data(self.apikey, 'fork_repo',
717 id_, params = _build_data(self.apikey, 'fork_repo',
683 repoid=self.REPO,
718 repoid=self.REPO,
684 fork_name=fork_name,
719 fork_name=fork_name,
685 owner=TEST_USER_ADMIN_LOGIN,
720 owner=TEST_USER_ADMIN_LOGIN,
686 )
721 )
687 response = self.app.post(API_URL, content_type='application/json',
722 response = self.app.post(API_URL, content_type='application/json',
688 params=params)
723 params=params)
689
724
690 expected = 'failed to fork repository `%s` as `%s`' % (self.REPO,
725 expected = 'failed to fork repository `%s` as `%s`' % (self.REPO,
691 fork_name)
726 fork_name)
692 self._compare_error(id_, expected, given=response.body)
727 self._compare_error(id_, expected, given=response.body)
693
728
694 def test_api_get_users_group(self):
729 def test_api_get_users_group(self):
695 id_, params = _build_data(self.apikey, 'get_users_group',
730 id_, params = _build_data(self.apikey, 'get_users_group',
696 usersgroupid=TEST_USERS_GROUP)
731 usersgroupid=TEST_USERS_GROUP)
697 response = self.app.post(API_URL, content_type='application/json',
732 response = self.app.post(API_URL, content_type='application/json',
698 params=params)
733 params=params)
699
734
700 users_group = UsersGroupModel().get_group(TEST_USERS_GROUP)
735 users_group = UsersGroupModel().get_group(TEST_USERS_GROUP)
701 members = []
736 members = []
702 for user in users_group.members:
737 for user in users_group.members:
703 user = user.user
738 user = user.user
704 members.append(user.get_api_data())
739 members.append(user.get_api_data())
705
740
706 ret = users_group.get_api_data()
741 ret = users_group.get_api_data()
707 ret['members'] = members
742 ret['members'] = members
708 expected = ret
743 expected = ret
709 self._compare_ok(id_, expected, given=response.body)
744 self._compare_ok(id_, expected, given=response.body)
710
745
711 def test_api_get_users_groups(self):
746 def test_api_get_users_groups(self):
712
747
713 make_users_group('test_users_group2')
748 make_users_group('test_users_group2')
714
749
715 id_, params = _build_data(self.apikey, 'get_users_groups',)
750 id_, params = _build_data(self.apikey, 'get_users_groups',)
716 response = self.app.post(API_URL, content_type='application/json',
751 response = self.app.post(API_URL, content_type='application/json',
717 params=params)
752 params=params)
718
753
719 expected = []
754 expected = []
720 for gr_name in [TEST_USERS_GROUP, 'test_users_group2']:
755 for gr_name in [TEST_USERS_GROUP, 'test_users_group2']:
721 users_group = UsersGroupModel().get_group(gr_name)
756 users_group = UsersGroupModel().get_group(gr_name)
722 ret = users_group.get_api_data()
757 ret = users_group.get_api_data()
723 expected.append(ret)
758 expected.append(ret)
724 self._compare_ok(id_, expected, given=response.body)
759 self._compare_ok(id_, expected, given=response.body)
725
760
726 UsersGroupModel().delete(users_group='test_users_group2')
761 UsersGroupModel().delete(users_group='test_users_group2')
727 self.Session().commit()
762 self.Session().commit()
728
763
729 def test_api_create_users_group(self):
764 def test_api_create_users_group(self):
730 group_name = 'some_new_group'
765 group_name = 'some_new_group'
731 id_, params = _build_data(self.apikey, 'create_users_group',
766 id_, params = _build_data(self.apikey, 'create_users_group',
732 group_name=group_name)
767 group_name=group_name)
733 response = self.app.post(API_URL, content_type='application/json',
768 response = self.app.post(API_URL, content_type='application/json',
734 params=params)
769 params=params)
735
770
736 ret = {
771 ret = {
737 'msg': 'created new users group `%s`' % group_name,
772 'msg': 'created new users group `%s`' % group_name,
738 'users_group': jsonify(UsersGroupModel()\
773 'users_group': jsonify(UsersGroupModel()\
739 .get_by_name(group_name)\
774 .get_by_name(group_name)\
740 .get_api_data())
775 .get_api_data())
741 }
776 }
742 expected = ret
777 expected = ret
743 self._compare_ok(id_, expected, given=response.body)
778 self._compare_ok(id_, expected, given=response.body)
744
779
745 destroy_users_group(group_name)
780 destroy_users_group(group_name)
746
781
747 def test_api_get_users_group_that_exist(self):
782 def test_api_get_users_group_that_exist(self):
748 id_, params = _build_data(self.apikey, 'create_users_group',
783 id_, params = _build_data(self.apikey, 'create_users_group',
749 group_name=TEST_USERS_GROUP)
784 group_name=TEST_USERS_GROUP)
750 response = self.app.post(API_URL, content_type='application/json',
785 response = self.app.post(API_URL, content_type='application/json',
751 params=params)
786 params=params)
752
787
753 expected = "users group `%s` already exist" % TEST_USERS_GROUP
788 expected = "users group `%s` already exist" % TEST_USERS_GROUP
754 self._compare_error(id_, expected, given=response.body)
789 self._compare_error(id_, expected, given=response.body)
755
790
756 @mock.patch.object(UsersGroupModel, 'create', crash)
791 @mock.patch.object(UsersGroupModel, 'create', crash)
757 def test_api_get_users_group_exception_occurred(self):
792 def test_api_get_users_group_exception_occurred(self):
758 group_name = 'exception_happens'
793 group_name = 'exception_happens'
759 id_, params = _build_data(self.apikey, 'create_users_group',
794 id_, params = _build_data(self.apikey, 'create_users_group',
760 group_name=group_name)
795 group_name=group_name)
761 response = self.app.post(API_URL, content_type='application/json',
796 response = self.app.post(API_URL, content_type='application/json',
762 params=params)
797 params=params)
763
798
764 expected = 'failed to create group `%s`' % group_name
799 expected = 'failed to create group `%s`' % group_name
765 self._compare_error(id_, expected, given=response.body)
800 self._compare_error(id_, expected, given=response.body)
766
801
767 def test_api_add_user_to_users_group(self):
802 def test_api_add_user_to_users_group(self):
768 gr_name = 'test_group'
803 gr_name = 'test_group'
769 UsersGroupModel().create(gr_name)
804 UsersGroupModel().create(gr_name)
770 self.Session().commit()
805 self.Session().commit()
771 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
806 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
772 usersgroupid=gr_name,
807 usersgroupid=gr_name,
773 userid=TEST_USER_ADMIN_LOGIN)
808 userid=TEST_USER_ADMIN_LOGIN)
774 response = self.app.post(API_URL, content_type='application/json',
809 response = self.app.post(API_URL, content_type='application/json',
775 params=params)
810 params=params)
776
811
777 expected = {
812 expected = {
778 'msg': 'added member `%s` to users group `%s`' % (
813 'msg': 'added member `%s` to users group `%s`' % (
779 TEST_USER_ADMIN_LOGIN, gr_name
814 TEST_USER_ADMIN_LOGIN, gr_name
780 ),
815 ),
781 'success': True}
816 'success': True}
782 self._compare_ok(id_, expected, given=response.body)
817 self._compare_ok(id_, expected, given=response.body)
783
818
784 UsersGroupModel().delete(users_group=gr_name)
819 UsersGroupModel().delete(users_group=gr_name)
785 self.Session().commit()
820 self.Session().commit()
786
821
787 def test_api_add_user_to_users_group_that_doesnt_exist(self):
822 def test_api_add_user_to_users_group_that_doesnt_exist(self):
788 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
823 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
789 usersgroupid='false-group',
824 usersgroupid='false-group',
790 userid=TEST_USER_ADMIN_LOGIN)
825 userid=TEST_USER_ADMIN_LOGIN)
791 response = self.app.post(API_URL, content_type='application/json',
826 response = self.app.post(API_URL, content_type='application/json',
792 params=params)
827 params=params)
793
828
794 expected = 'users group `%s` does not exist' % 'false-group'
829 expected = 'users group `%s` does not exist' % 'false-group'
795 self._compare_error(id_, expected, given=response.body)
830 self._compare_error(id_, expected, given=response.body)
796
831
797 @mock.patch.object(UsersGroupModel, 'add_user_to_group', crash)
832 @mock.patch.object(UsersGroupModel, 'add_user_to_group', crash)
798 def test_api_add_user_to_users_group_exception_occurred(self):
833 def test_api_add_user_to_users_group_exception_occurred(self):
799 gr_name = 'test_group'
834 gr_name = 'test_group'
800 UsersGroupModel().create(gr_name)
835 UsersGroupModel().create(gr_name)
801 self.Session().commit()
836 self.Session().commit()
802 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
837 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
803 usersgroupid=gr_name,
838 usersgroupid=gr_name,
804 userid=TEST_USER_ADMIN_LOGIN)
839 userid=TEST_USER_ADMIN_LOGIN)
805 response = self.app.post(API_URL, content_type='application/json',
840 response = self.app.post(API_URL, content_type='application/json',
806 params=params)
841 params=params)
807
842
808 expected = 'failed to add member to users group `%s`' % gr_name
843 expected = 'failed to add member to users group `%s`' % gr_name
809 self._compare_error(id_, expected, given=response.body)
844 self._compare_error(id_, expected, given=response.body)
810
845
811 UsersGroupModel().delete(users_group=gr_name)
846 UsersGroupModel().delete(users_group=gr_name)
812 self.Session().commit()
847 self.Session().commit()
813
848
814 def test_api_remove_user_from_users_group(self):
849 def test_api_remove_user_from_users_group(self):
815 gr_name = 'test_group_3'
850 gr_name = 'test_group_3'
816 gr = UsersGroupModel().create(gr_name)
851 gr = UsersGroupModel().create(gr_name)
817 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
852 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
818 self.Session().commit()
853 self.Session().commit()
819 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
854 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
820 usersgroupid=gr_name,
855 usersgroupid=gr_name,
821 userid=TEST_USER_ADMIN_LOGIN)
856 userid=TEST_USER_ADMIN_LOGIN)
822 response = self.app.post(API_URL, content_type='application/json',
857 response = self.app.post(API_URL, content_type='application/json',
823 params=params)
858 params=params)
824
859
825 expected = {
860 expected = {
826 'msg': 'removed member `%s` from users group `%s`' % (
861 'msg': 'removed member `%s` from users group `%s`' % (
827 TEST_USER_ADMIN_LOGIN, gr_name
862 TEST_USER_ADMIN_LOGIN, gr_name
828 ),
863 ),
829 'success': True}
864 'success': True}
830 self._compare_ok(id_, expected, given=response.body)
865 self._compare_ok(id_, expected, given=response.body)
831
866
832 UsersGroupModel().delete(users_group=gr_name)
867 UsersGroupModel().delete(users_group=gr_name)
833 self.Session().commit()
868 self.Session().commit()
834
869
835 @mock.patch.object(UsersGroupModel, 'remove_user_from_group', crash)
870 @mock.patch.object(UsersGroupModel, 'remove_user_from_group', crash)
836 def test_api_remove_user_from_users_group_exception_occurred(self):
871 def test_api_remove_user_from_users_group_exception_occurred(self):
837 gr_name = 'test_group_3'
872 gr_name = 'test_group_3'
838 gr = UsersGroupModel().create(gr_name)
873 gr = UsersGroupModel().create(gr_name)
839 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
874 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
840 self.Session().commit()
875 self.Session().commit()
841 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
876 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
842 usersgroupid=gr_name,
877 usersgroupid=gr_name,
843 userid=TEST_USER_ADMIN_LOGIN)
878 userid=TEST_USER_ADMIN_LOGIN)
844 response = self.app.post(API_URL, content_type='application/json',
879 response = self.app.post(API_URL, content_type='application/json',
845 params=params)
880 params=params)
846
881
847 expected = 'failed to remove member from users group `%s`' % gr_name
882 expected = 'failed to remove member from users group `%s`' % gr_name
848 self._compare_error(id_, expected, given=response.body)
883 self._compare_error(id_, expected, given=response.body)
849
884
850 UsersGroupModel().delete(users_group=gr_name)
885 UsersGroupModel().delete(users_group=gr_name)
851 self.Session().commit()
886 self.Session().commit()
852
887
853 @parameterized.expand([('none', 'repository.none'),
888 @parameterized.expand([('none', 'repository.none'),
854 ('read', 'repository.read'),
889 ('read', 'repository.read'),
855 ('write', 'repository.write'),
890 ('write', 'repository.write'),
856 ('admin', 'repository.admin')])
891 ('admin', 'repository.admin')])
857 def test_api_grant_user_permission(self, name, perm):
892 def test_api_grant_user_permission(self, name, perm):
858 id_, params = _build_data(self.apikey, 'grant_user_permission',
893 id_, params = _build_data(self.apikey, 'grant_user_permission',
859 repoid=self.REPO,
894 repoid=self.REPO,
860 userid=TEST_USER_ADMIN_LOGIN,
895 userid=TEST_USER_ADMIN_LOGIN,
861 perm=perm)
896 perm=perm)
862 response = self.app.post(API_URL, content_type='application/json',
897 response = self.app.post(API_URL, content_type='application/json',
863 params=params)
898 params=params)
864
899
865 ret = {
900 ret = {
866 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % (
901 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % (
867 perm, TEST_USER_ADMIN_LOGIN, self.REPO
902 perm, TEST_USER_ADMIN_LOGIN, self.REPO
868 ),
903 ),
869 'success': True
904 'success': True
870 }
905 }
871 expected = ret
906 expected = ret
872 self._compare_ok(id_, expected, given=response.body)
907 self._compare_ok(id_, expected, given=response.body)
873
908
874 def test_api_grant_user_permission_wrong_permission(self):
909 def test_api_grant_user_permission_wrong_permission(self):
875 perm = 'haha.no.permission'
910 perm = 'haha.no.permission'
876 id_, params = _build_data(self.apikey, 'grant_user_permission',
911 id_, params = _build_data(self.apikey, 'grant_user_permission',
877 repoid=self.REPO,
912 repoid=self.REPO,
878 userid=TEST_USER_ADMIN_LOGIN,
913 userid=TEST_USER_ADMIN_LOGIN,
879 perm=perm)
914 perm=perm)
880 response = self.app.post(API_URL, content_type='application/json',
915 response = self.app.post(API_URL, content_type='application/json',
881 params=params)
916 params=params)
882
917
883 expected = 'permission `%s` does not exist' % perm
918 expected = 'permission `%s` does not exist' % perm
884 self._compare_error(id_, expected, given=response.body)
919 self._compare_error(id_, expected, given=response.body)
885
920
886 @mock.patch.object(RepoModel, 'grant_user_permission', crash)
921 @mock.patch.object(RepoModel, 'grant_user_permission', crash)
887 def test_api_grant_user_permission_exception_when_adding(self):
922 def test_api_grant_user_permission_exception_when_adding(self):
888 perm = 'repository.read'
923 perm = 'repository.read'
889 id_, params = _build_data(self.apikey, 'grant_user_permission',
924 id_, params = _build_data(self.apikey, 'grant_user_permission',
890 repoid=self.REPO,
925 repoid=self.REPO,
891 userid=TEST_USER_ADMIN_LOGIN,
926 userid=TEST_USER_ADMIN_LOGIN,
892 perm=perm)
927 perm=perm)
893 response = self.app.post(API_URL, content_type='application/json',
928 response = self.app.post(API_URL, content_type='application/json',
894 params=params)
929 params=params)
895
930
896 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
931 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
897 TEST_USER_ADMIN_LOGIN, self.REPO
932 TEST_USER_ADMIN_LOGIN, self.REPO
898 )
933 )
899 self._compare_error(id_, expected, given=response.body)
934 self._compare_error(id_, expected, given=response.body)
900
935
901 def test_api_revoke_user_permission(self):
936 def test_api_revoke_user_permission(self):
902 id_, params = _build_data(self.apikey, 'revoke_user_permission',
937 id_, params = _build_data(self.apikey, 'revoke_user_permission',
903 repoid=self.REPO,
938 repoid=self.REPO,
904 userid=TEST_USER_ADMIN_LOGIN,)
939 userid=TEST_USER_ADMIN_LOGIN,)
905 response = self.app.post(API_URL, content_type='application/json',
940 response = self.app.post(API_URL, content_type='application/json',
906 params=params)
941 params=params)
907
942
908 expected = {
943 expected = {
909 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
944 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
910 TEST_USER_ADMIN_LOGIN, self.REPO
945 TEST_USER_ADMIN_LOGIN, self.REPO
911 ),
946 ),
912 'success': True
947 'success': True
913 }
948 }
914 self._compare_ok(id_, expected, given=response.body)
949 self._compare_ok(id_, expected, given=response.body)
915
950
916 @mock.patch.object(RepoModel, 'revoke_user_permission', crash)
951 @mock.patch.object(RepoModel, 'revoke_user_permission', crash)
917 def test_api_revoke_user_permission_exception_when_adding(self):
952 def test_api_revoke_user_permission_exception_when_adding(self):
918 id_, params = _build_data(self.apikey, 'revoke_user_permission',
953 id_, params = _build_data(self.apikey, 'revoke_user_permission',
919 repoid=self.REPO,
954 repoid=self.REPO,
920 userid=TEST_USER_ADMIN_LOGIN,)
955 userid=TEST_USER_ADMIN_LOGIN,)
921 response = self.app.post(API_URL, content_type='application/json',
956 response = self.app.post(API_URL, content_type='application/json',
922 params=params)
957 params=params)
923
958
924 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
959 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
925 TEST_USER_ADMIN_LOGIN, self.REPO
960 TEST_USER_ADMIN_LOGIN, self.REPO
926 )
961 )
927 self._compare_error(id_, expected, given=response.body)
962 self._compare_error(id_, expected, given=response.body)
928
963
929 @parameterized.expand([('none', 'repository.none'),
964 @parameterized.expand([('none', 'repository.none'),
930 ('read', 'repository.read'),
965 ('read', 'repository.read'),
931 ('write', 'repository.write'),
966 ('write', 'repository.write'),
932 ('admin', 'repository.admin')])
967 ('admin', 'repository.admin')])
933 def test_api_grant_users_group_permission(self, name, perm):
968 def test_api_grant_users_group_permission(self, name, perm):
934 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
969 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
935 repoid=self.REPO,
970 repoid=self.REPO,
936 usersgroupid=TEST_USERS_GROUP,
971 usersgroupid=TEST_USERS_GROUP,
937 perm=perm)
972 perm=perm)
938 response = self.app.post(API_URL, content_type='application/json',
973 response = self.app.post(API_URL, content_type='application/json',
939 params=params)
974 params=params)
940
975
941 ret = {
976 ret = {
942 'msg': 'Granted perm: `%s` for users group: `%s` in repo: `%s`' % (
977 'msg': 'Granted perm: `%s` for users group: `%s` in repo: `%s`' % (
943 perm, TEST_USERS_GROUP, self.REPO
978 perm, TEST_USERS_GROUP, self.REPO
944 ),
979 ),
945 'success': True
980 'success': True
946 }
981 }
947 expected = ret
982 expected = ret
948 self._compare_ok(id_, expected, given=response.body)
983 self._compare_ok(id_, expected, given=response.body)
949
984
950 def test_api_grant_users_group_permission_wrong_permission(self):
985 def test_api_grant_users_group_permission_wrong_permission(self):
951 perm = 'haha.no.permission'
986 perm = 'haha.no.permission'
952 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
987 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
953 repoid=self.REPO,
988 repoid=self.REPO,
954 usersgroupid=TEST_USERS_GROUP,
989 usersgroupid=TEST_USERS_GROUP,
955 perm=perm)
990 perm=perm)
956 response = self.app.post(API_URL, content_type='application/json',
991 response = self.app.post(API_URL, content_type='application/json',
957 params=params)
992 params=params)
958
993
959 expected = 'permission `%s` does not exist' % perm
994 expected = 'permission `%s` does not exist' % perm
960 self._compare_error(id_, expected, given=response.body)
995 self._compare_error(id_, expected, given=response.body)
961
996
962 @mock.patch.object(RepoModel, 'grant_users_group_permission', crash)
997 @mock.patch.object(RepoModel, 'grant_users_group_permission', crash)
963 def test_api_grant_users_group_permission_exception_when_adding(self):
998 def test_api_grant_users_group_permission_exception_when_adding(self):
964 perm = 'repository.read'
999 perm = 'repository.read'
965 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1000 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
966 repoid=self.REPO,
1001 repoid=self.REPO,
967 usersgroupid=TEST_USERS_GROUP,
1002 usersgroupid=TEST_USERS_GROUP,
968 perm=perm)
1003 perm=perm)
969 response = self.app.post(API_URL, content_type='application/json',
1004 response = self.app.post(API_URL, content_type='application/json',
970 params=params)
1005 params=params)
971
1006
972 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
1007 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
973 TEST_USERS_GROUP, self.REPO
1008 TEST_USERS_GROUP, self.REPO
974 )
1009 )
975 self._compare_error(id_, expected, given=response.body)
1010 self._compare_error(id_, expected, given=response.body)
976
1011
977 def test_api_revoke_users_group_permission(self):
1012 def test_api_revoke_users_group_permission(self):
978 RepoModel().grant_users_group_permission(repo=self.REPO,
1013 RepoModel().grant_users_group_permission(repo=self.REPO,
979 group_name=TEST_USERS_GROUP,
1014 group_name=TEST_USERS_GROUP,
980 perm='repository.read')
1015 perm='repository.read')
981 self.Session().commit()
1016 self.Session().commit()
982 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1017 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
983 repoid=self.REPO,
1018 repoid=self.REPO,
984 usersgroupid=TEST_USERS_GROUP,)
1019 usersgroupid=TEST_USERS_GROUP,)
985 response = self.app.post(API_URL, content_type='application/json',
1020 response = self.app.post(API_URL, content_type='application/json',
986 params=params)
1021 params=params)
987
1022
988 expected = {
1023 expected = {
989 'msg': 'Revoked perm for users group: `%s` in repo: `%s`' % (
1024 'msg': 'Revoked perm for users group: `%s` in repo: `%s`' % (
990 TEST_USERS_GROUP, self.REPO
1025 TEST_USERS_GROUP, self.REPO
991 ),
1026 ),
992 'success': True
1027 'success': True
993 }
1028 }
994 self._compare_ok(id_, expected, given=response.body)
1029 self._compare_ok(id_, expected, given=response.body)
995
1030
996 @mock.patch.object(RepoModel, 'revoke_users_group_permission', crash)
1031 @mock.patch.object(RepoModel, 'revoke_users_group_permission', crash)
997 def test_api_revoke_users_group_permission_exception_when_adding(self):
1032 def test_api_revoke_users_group_permission_exception_when_adding(self):
998
1033
999 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1034 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1000 repoid=self.REPO,
1035 repoid=self.REPO,
1001 usersgroupid=TEST_USERS_GROUP,)
1036 usersgroupid=TEST_USERS_GROUP,)
1002 response = self.app.post(API_URL, content_type='application/json',
1037 response = self.app.post(API_URL, content_type='application/json',
1003 params=params)
1038 params=params)
1004
1039
1005 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
1040 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
1006 TEST_USERS_GROUP, self.REPO
1041 TEST_USERS_GROUP, self.REPO
1007 )
1042 )
1008 self._compare_error(id_, expected, given=response.body)
1043 self._compare_error(id_, expected, given=response.body)
General Comments 0
You need to be logged in to leave comments. Login now