Mercurial > kallithea
comparison rhodecode/controllers/api/__init__.py @ 2379:7ac09514a178 beta
created rhodecode-api binary script for working with api via cli
- created docs
- moved the backup script to bin folder
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Sun, 03 Jun 2012 20:35:13 +0200 |
parents | 12ceeda33339 |
children | c785ad556d44 |
comparison
equal
deleted
inserted
replaced
2378:04ef27ce939e | 2379:7ac09514a178 |
---|---|
55 | 55 |
56 def __str__(self): | 56 def __str__(self): |
57 return str(self.message) | 57 return str(self.message) |
58 | 58 |
59 | 59 |
60 def jsonrpc_error(message, code=None): | 60 def jsonrpc_error(message, retid=None, code=None): |
61 """ | 61 """ |
62 Generate a Response object with a JSON-RPC error body | 62 Generate a Response object with a JSON-RPC error body |
63 """ | 63 """ |
64 from pylons.controllers.util import Response | 64 from pylons.controllers.util import Response |
65 resp = Response(body=json.dumps(dict(id=None, result=None, error=message)), | 65 return Response( |
66 status=code, | 66 body=json.dumps(dict(id=retid, result=None, error=message)), |
67 content_type='application/json') | 67 status=code, |
68 return resp | 68 content_type='application/json' |
69 ) | |
69 | 70 |
70 | 71 |
71 class JSONRPCController(WSGIController): | 72 class JSONRPCController(WSGIController): |
72 """ | 73 """ |
73 A WSGI-speaking JSON-RPC controller class | 74 A WSGI-speaking JSON-RPC controller class |
92 def __call__(self, environ, start_response): | 93 def __call__(self, environ, start_response): |
93 """ | 94 """ |
94 Parse the request body as JSON, look up the method on the | 95 Parse the request body as JSON, look up the method on the |
95 controller and if it exists, dispatch to it. | 96 controller and if it exists, dispatch to it. |
96 """ | 97 """ |
98 self._req_id = None | |
97 if 'CONTENT_LENGTH' not in environ: | 99 if 'CONTENT_LENGTH' not in environ: |
98 log.debug("No Content-Length") | 100 log.debug("No Content-Length") |
99 return jsonrpc_error(message="No Content-Length in request") | 101 return jsonrpc_error(retid=self._req_id, |
102 message="No Content-Length in request") | |
100 else: | 103 else: |
101 length = environ['CONTENT_LENGTH'] or 0 | 104 length = environ['CONTENT_LENGTH'] or 0 |
102 length = int(environ['CONTENT_LENGTH']) | 105 length = int(environ['CONTENT_LENGTH']) |
103 log.debug('Content-Length: %s' % length) | 106 log.debug('Content-Length: %s' % length) |
104 | 107 |
105 if length == 0: | 108 if length == 0: |
106 log.debug("Content-Length is 0") | 109 log.debug("Content-Length is 0") |
107 return jsonrpc_error(message="Content-Length is 0") | 110 return jsonrpc_error(retid=self._req_id, |
111 message="Content-Length is 0") | |
108 | 112 |
109 raw_body = environ['wsgi.input'].read(length) | 113 raw_body = environ['wsgi.input'].read(length) |
110 | 114 |
111 try: | 115 try: |
112 json_body = json.loads(urllib.unquote_plus(raw_body)) | 116 json_body = json.loads(urllib.unquote_plus(raw_body)) |
113 except ValueError, e: | 117 except ValueError, e: |
114 # catch JSON errors Here | 118 # catch JSON errors Here |
115 return jsonrpc_error(message="JSON parse error ERR:%s RAW:%r" \ | 119 return jsonrpc_error(retid=self._req_id, |
120 message="JSON parse error ERR:%s RAW:%r" \ | |
116 % (e, urllib.unquote_plus(raw_body))) | 121 % (e, urllib.unquote_plus(raw_body))) |
117 | 122 |
118 # check AUTH based on API KEY | 123 # check AUTH based on API KEY |
119 try: | 124 try: |
120 self._req_api_key = json_body['api_key'] | 125 self._req_api_key = json_body['api_key'] |
124 log.debug( | 129 log.debug( |
125 'method: %s, params: %s' % (self._req_method, | 130 'method: %s, params: %s' % (self._req_method, |
126 self._request_params) | 131 self._request_params) |
127 ) | 132 ) |
128 except KeyError, e: | 133 except KeyError, e: |
129 return jsonrpc_error(message='Incorrect JSON query missing %s' % e) | 134 return jsonrpc_error(retid=self._req_id, |
135 message='Incorrect JSON query missing %s' % e) | |
130 | 136 |
131 # check if we can find this session using api_key | 137 # check if we can find this session using api_key |
132 try: | 138 try: |
133 u = User.get_by_api_key(self._req_api_key) | 139 u = User.get_by_api_key(self._req_api_key) |
134 if u is None: | 140 if u is None: |
135 return jsonrpc_error(message='Invalid API KEY') | 141 return jsonrpc_error(retid=self._req_id, |
142 message='Invalid API KEY') | |
136 auth_u = AuthUser(u.user_id, self._req_api_key) | 143 auth_u = AuthUser(u.user_id, self._req_api_key) |
137 except Exception, e: | 144 except Exception, e: |
138 return jsonrpc_error(message='Invalid API KEY') | 145 return jsonrpc_error(retid=self._req_id, |
146 message='Invalid API KEY') | |
139 | 147 |
140 self._error = None | 148 self._error = None |
141 try: | 149 try: |
142 self._func = self._find_method() | 150 self._func = self._find_method() |
143 except AttributeError, e: | 151 except AttributeError, e: |
144 return jsonrpc_error(message=str(e)) | 152 return jsonrpc_error(retid=self._req_id, |
153 message=str(e)) | |
145 | 154 |
146 # now that we have a method, add self._req_params to | 155 # now that we have a method, add self._req_params to |
147 # self.kargs and dispatch control to WGIController | 156 # self.kargs and dispatch control to WGIController |
148 argspec = inspect.getargspec(self._func) | 157 argspec = inspect.getargspec(self._func) |
149 arglist = argspec[0][1:] | 158 arglist = argspec[0][1:] |
162 # This attribute will need to be first param of a method that uses | 171 # This attribute will need to be first param of a method that uses |
163 # api_key, which is translated to instance of user at that name | 172 # api_key, which is translated to instance of user at that name |
164 USER_SESSION_ATTR = 'apiuser' | 173 USER_SESSION_ATTR = 'apiuser' |
165 | 174 |
166 if USER_SESSION_ATTR not in arglist: | 175 if USER_SESSION_ATTR not in arglist: |
167 return jsonrpc_error(message='This method [%s] does not support ' | 176 return jsonrpc_error( |
168 'authentication (missing %s param)' % | 177 retid=self._req_id, |
169 (self._func.__name__, USER_SESSION_ATTR)) | 178 message='This method [%s] does not support ' |
179 'authentication (missing %s param)' % ( | |
180 self._func.__name__, USER_SESSION_ATTR) | |
181 ) | |
170 | 182 |
171 # get our arglist and check if we provided them as args | 183 # get our arglist and check if we provided them as args |
172 for arg, default in func_kwargs.iteritems(): | 184 for arg, default in func_kwargs.iteritems(): |
173 if arg == USER_SESSION_ATTR: | 185 if arg == USER_SESSION_ATTR: |
174 # USER_SESSION_ATTR is something translated from api key and | 186 # USER_SESSION_ATTR is something translated from api key and |
177 | 189 |
178 # skip the required param check if it's default value is | 190 # skip the required param check if it's default value is |
179 # NotImplementedType (default_empty) | 191 # NotImplementedType (default_empty) |
180 if (default == default_empty and arg not in self._request_params): | 192 if (default == default_empty and arg not in self._request_params): |
181 return jsonrpc_error( | 193 return jsonrpc_error( |
194 retid=self._req_id, | |
182 message=( | 195 message=( |
183 'Missing non optional `%s` arg in JSON DATA' % arg | 196 'Missing non optional `%s` arg in JSON DATA' % arg |
184 ) | 197 ) |
185 ) | 198 ) |
186 | 199 |