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