Show More
@@ -6,12 +6,12 b' API' | |||
|
6 | 6 | |
|
7 | 7 | |
|
8 | 8 | Starting from RhodeCode version 1.2 a simple API was implemented. |
|
9 |
There's |
|
|
9 | There's a single schema for calling all api methods. API is implemented | |
|
10 | 10 | with JSON protocol both ways. An url to send API request in RhodeCode is |
|
11 |
<your |
|
|
11 | <your_server>/_admin/api | |
|
12 | 12 | |
|
13 | 13 | |
|
14 |
|
|
|
14 | All clients need to send JSON data in such format:: | |
|
15 | 15 | |
|
16 | 16 | { |
|
17 | 17 | "api_key":"<api_key>", |
@@ -19,16 +19,20 b' Clients need to send JSON data in such f' | |||
|
19 | 19 | "args":{"<arg_key>":"<arg_val>"} |
|
20 | 20 | } |
|
21 | 21 | |
|
22 | Simply provide api_key for access and permission validation | |
|
23 | method is name of method to call | |
|
24 | and args is an key:value list of arguments to pass to method | |
|
22 | Example call for autopulling remotes repos using curl:: | |
|
23 | curl https://server.com/_admin/api -X POST -H 'content-type:text/plain' --data-binary '{"api_key":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull","args":{"repo":"CPython"}}' | |
|
24 | ||
|
25 | Simply provide | |
|
26 | - *api_key* for access and permission validation. | |
|
27 | - *method* is name of method to call | |
|
28 | - *args* is an key:value list of arguments to pass to method | |
|
25 | 29 | |
|
26 | 30 | .. note:: |
|
27 | 31 | |
|
28 | 32 | api_key can be found in your user account page |
|
29 | 33 | |
|
30 | 34 | |
|
31 |
|
|
|
35 | RhodeCode API will return always a JSON formatted answer:: | |
|
32 | 36 | |
|
33 | 37 | { |
|
34 | 38 | "result": "<result>", |
@@ -36,7 +40,7 b' And will receive JSON formatted answer::' | |||
|
36 | 40 | } |
|
37 | 41 | |
|
38 | 42 | All responses from API will be `HTTP/1.0 200 OK`, if there's an error while |
|
39 |
calling api |
|
|
43 | calling api *error* key from response will contain failure description | |
|
40 | 44 | and result will be null. |
|
41 | 45 | |
|
42 | 46 | API METHODS |
@@ -47,11 +51,61 b' pull' | |||
|
47 | 51 | ---- |
|
48 | 52 | |
|
49 | 53 | Pulls given repo from remote location. Can be used to automatically keep |
|
50 |
remote repos upto date. This command can be executed only using a |
|
|
51 | api_key | |
|
54 | remote repos up to date. This command can be executed only using api_key | |
|
55 | belonging to user with admin rights | |
|
52 | 56 | |
|
53 | :: | |
|
57 | INPUT:: | |
|
58 | ||
|
54 | 59 | api_key:"<api_key>" |
|
55 | 60 | method: "pull" |
|
56 | 61 | args: {"repo":<repo_name>} |
|
57 | 62 |
|
|
63 | OUTPUT:: | |
|
64 | ||
|
65 | result:"Pulled from <repo_name>" | |
|
66 | error:null | |
|
67 | ||
|
68 | ||
|
69 | create_user | |
|
70 | ----------- | |
|
71 | ||
|
72 | Creates new user in RhodeCode. This command can be executed only using api_key | |
|
73 | belonging to user with admin rights | |
|
74 | ||
|
75 | INPUT:: | |
|
76 | ||
|
77 | api_key:"<api_key>" | |
|
78 | method: "create_user" | |
|
79 | args: {"username": "<username>", | |
|
80 | "password": "<password>", | |
|
81 | "active": "<bool>", | |
|
82 | "admin": "<bool>", | |
|
83 | "name": "<firstname>", | |
|
84 | "lastname": "<lastname>", | |
|
85 | "email": "<useremail>"} | |
|
86 | ||
|
87 | OUTPUT:: | |
|
88 | ||
|
89 | result:{"id": <newuserid>, | |
|
90 | "msg":"created new user <username>"} | |
|
91 | error:null | |
|
92 | ||
|
93 | ||
|
94 | create_users_group | |
|
95 | ------------------ | |
|
96 | ||
|
97 | creates new users group. This command can be executed only using api_key | |
|
98 | belonging to user with admin rights | |
|
99 | ||
|
100 | INPUT:: | |
|
101 | ||
|
102 | api_key:"<api_key>" | |
|
103 | method: "create_user" | |
|
104 | args: {"name": "<groupname>", | |
|
105 | "active":"<bool>"} | |
|
106 | ||
|
107 | OUTPUT:: | |
|
108 | ||
|
109 | result:{"id": <newusersgroupid>, | |
|
110 | "msg":"created new users group <groupname>"} | |
|
111 | error:null |
@@ -136,25 +136,29 b' class JSONRPCController(WSGIController):' | |||
|
136 | 136 | |
|
137 | 137 | # this is little trick to inject logged in user for |
|
138 | 138 | # perms decorators to work they expect the controller class to have |
|
139 | # rhodecode_user set | |
|
139 | # rhodecode_user attribute set | |
|
140 | 140 | self.rhodecode_user = auth_u |
|
141 | 141 | |
|
142 | if 'user' not in arglist: | |
|
142 | # This attribute will need to be first param of a method that uses | |
|
143 | # api_key, which is translated to instance of user at that name | |
|
144 | USER_SESSION_ATTR = 'apiuser' | |
|
145 | ||
|
146 | if USER_SESSION_ATTR not in arglist: | |
|
143 | 147 | return jsonrpc_error(message='This method [%s] does not support ' |
|
144 |
'authentication (missing |
|
|
145 | self._func.__name__) | |
|
148 | 'authentication (missing %s param)' % | |
|
149 | (self._func.__name__, USER_SESSION_ATTR)) | |
|
146 | 150 | |
|
147 | 151 | # get our arglist and check if we provided them as args |
|
148 | 152 | for arg in arglist: |
|
149 |
if arg == |
|
|
150 |
# |
|
|
151 | # checked before | |
|
153 | if arg == USER_SESSION_ATTR: | |
|
154 | # USER_SESSION_ATTR is something translated from api key and | |
|
155 | # this is checked before so we don't need validate it | |
|
152 | 156 | continue |
|
153 | 157 | |
|
154 | 158 | if not self._req_params or arg not in self._req_params: |
|
155 | 159 | return jsonrpc_error(message='Missing %s arg in JSON DATA' % arg) |
|
156 | 160 | |
|
157 |
self._rpc_args = |
|
|
161 | self._rpc_args = {USER_SESSION_ATTR:u} | |
|
158 | 162 | self._rpc_args.update(self._req_params) |
|
159 | 163 | |
|
160 | 164 | self._rpc_args['action'] = self._req_method |
@@ -183,7 +187,6 b' class JSONRPCController(WSGIController):' | |||
|
183 | 187 | """ |
|
184 | 188 | try: |
|
185 | 189 | raw_response = self._inspect_call(self._func) |
|
186 | print raw_response | |
|
187 | 190 | if isinstance(raw_response, HTTPError): |
|
188 | 191 | self._error = str(raw_response) |
|
189 | 192 | except JSONRPCError as e: |
@@ -223,3 +226,4 b' class JSONRPCController(WSGIController):' | |||
|
223 | 226 | return func |
|
224 | 227 | else: |
|
225 | 228 | raise AttributeError("No such method: %s" % self._req_method) |
|
229 |
@@ -1,7 +1,14 b'' | |||
|
1 | import traceback | |
|
2 | import logging | |
|
3 | ||
|
1 | 4 | from rhodecode.controllers.api import JSONRPCController, JSONRPCError |
|
2 | 5 | from rhodecode.lib.auth import HasPermissionAllDecorator |
|
3 | 6 | from rhodecode.model.scm import ScmModel |
|
4 | 7 | |
|
8 | from rhodecode.model.db import User, UsersGroup | |
|
9 | ||
|
10 | log = logging.getLogger(__name__) | |
|
11 | ||
|
5 | 12 | |
|
6 | 13 | class ApiController(JSONRPCController): |
|
7 | 14 | """ |
@@ -20,13 +27,13 b' class ApiController(JSONRPCController):' | |||
|
20 | 27 | """ |
|
21 | 28 | |
|
22 | 29 | @HasPermissionAllDecorator('hg.admin') |
|
23 | def pull(self, user, repo): | |
|
30 | def pull(self, apiuser, repo): | |
|
24 | 31 | """ |
|
25 | 32 | Dispatch pull action on given repo |
|
26 | 33 | |
|
27 | 34 | |
|
28 | param user: | |
|
29 | param repo: | |
|
35 | :param user: | |
|
36 | :param repo: | |
|
30 | 37 | """ |
|
31 | 38 | |
|
32 | 39 | try: |
@@ -36,5 +43,53 b' class ApiController(JSONRPCController):' | |||
|
36 | 43 | raise JSONRPCError('Unable to pull changes from "%s"' % repo) |
|
37 | 44 | |
|
38 | 45 | |
|
46 | @HasPermissionAllDecorator('hg.admin') | |
|
47 | def create_user(self, apiuser, username, password, active, admin, name, | |
|
48 | lastname, email): | |
|
49 | """ | |
|
50 | Creates new user | |
|
51 | ||
|
52 | :param apiuser: | |
|
53 | :param username: | |
|
54 | :param password: | |
|
55 | :param active: | |
|
56 | :param admin: | |
|
57 | :param name: | |
|
58 | :param lastname: | |
|
59 | :param email: | |
|
60 | """ | |
|
61 | ||
|
62 | form_data = dict(username=username, | |
|
63 | password=password, | |
|
64 | active=active, | |
|
65 | admin=admin, | |
|
66 | name=name, | |
|
67 | lastname=lastname, | |
|
68 | email=email) | |
|
69 | try: | |
|
70 | u = User.create(form_data) | |
|
71 | return {'id':u.user_id, | |
|
72 | 'msg':'created new user %s' % name} | |
|
73 | except Exception: | |
|
74 | log.error(traceback.format_exc()) | |
|
75 | raise JSONRPCError('failed to create user %s' % name) | |
|
39 | 76 | |
|
40 | 77 | |
|
78 | @HasPermissionAllDecorator('hg.admin') | |
|
79 | def create_users_group(self, apiuser, name, active): | |
|
80 | """ | |
|
81 | Creates an new usergroup | |
|
82 | ||
|
83 | :param name: | |
|
84 | :param active: | |
|
85 | """ | |
|
86 | form_data = {'users_group_name':name, | |
|
87 | 'users_group_active':active} | |
|
88 | try: | |
|
89 | ug = UsersGroup.create(form_data) | |
|
90 | return {'id':ug.users_group_id, | |
|
91 | 'msg':'created new users group %s' % name} | |
|
92 | except Exception: | |
|
93 | log.error(traceback.format_exc()) | |
|
94 | raise JSONRPCError('failed to create group %s' % name) | |
|
95 | No newline at end of file |
@@ -38,12 +38,13 b' from beaker.cache import cache_region, r' | |||
|
38 | 38 | |
|
39 | 39 | from vcs import get_backend |
|
40 | 40 | from vcs.utils.helpers import get_scm |
|
41 |
from vcs.exceptions import |
|
|
41 | from vcs.exceptions import VCSError | |
|
42 | 42 | from vcs.utils.lazy import LazyProperty |
|
43 | from vcs.nodes import FileNode | |
|
44 | 43 | |
|
45 | 44 | from rhodecode.lib.exceptions import UsersGroupsAssignedException |
|
46 | from rhodecode.lib import str2bool, json, safe_str, get_changeset_safe | |
|
45 | from rhodecode.lib import str2bool, json, safe_str, get_changeset_safe,\ | |
|
46 | generate_api_key | |
|
47 | ||
|
47 | 48 | from rhodecode.model.meta import Base, Session |
|
48 | 49 | from rhodecode.model.caching_query import FromCache |
|
49 | 50 | |
@@ -298,6 +299,25 b' class User(Base, BaseModel):' | |||
|
298 | 299 | Session.commit() |
|
299 | 300 | log.debug('updated user %s lastlogin', self.username) |
|
300 | 301 | |
|
302 | @classmethod | |
|
303 | def create(cls, form_data): | |
|
304 | from rhodecode.lib.auth import get_crypt_password | |
|
305 | ||
|
306 | try: | |
|
307 | new_user = cls() | |
|
308 | for k, v in form_data.items(): | |
|
309 | if k == 'password': | |
|
310 | v = get_crypt_password(v) | |
|
311 | setattr(new_user, k, v) | |
|
312 | ||
|
313 | new_user.api_key = generate_api_key(form_data['username']) | |
|
314 | Session.add(new_user) | |
|
315 | Session.commit() | |
|
316 | return new_user | |
|
317 | except: | |
|
318 | log.error(traceback.format_exc()) | |
|
319 | Session.rollback() | |
|
320 | raise | |
|
301 | 321 | |
|
302 | 322 | class UserLog(Base, BaseModel): |
|
303 | 323 | __tablename__ = 'user_logs' |
@@ -362,6 +382,7 b' class UsersGroup(Base, BaseModel):' | |||
|
362 | 382 | |
|
363 | 383 | Session.add(new_users_group) |
|
364 | 384 | Session.commit() |
|
385 | return new_users_group | |
|
365 | 386 | except: |
|
366 | 387 | log.error(traceback.format_exc()) |
|
367 | 388 | Session.rollback() |
General Comments 0
You need to be logged in to leave comments.
Login now