Fix magic-folder 'status' command

This commit is contained in:
meejah 2016-05-23 14:48:07 -06:00 committed by Brian Warner
parent db40417886
commit 4509c7dafd
4 changed files with 31 additions and 36 deletions

View File

@ -224,6 +224,7 @@ class QueueMixin(HookMixin):
self._log("%d items to process" % len(to_process), ) self._log("%d items to process" % len(to_process), )
for item in to_process: for item in to_process:
self._process_history.appendleft(item)
try: try:
self._log(" processing '%r'" % (item,)) self._log(" processing '%r'" % (item,))
proc = yield self._process(item) proc = yield self._process(item)

View File

@ -218,13 +218,21 @@ class StatusOptions(BasedirOptions):
self['node-url'] = f.read().strip() self['node-url'] = f.read().strip()
def _get_json_for_fragment(options, fragment, method='GET'): def _get_json_for_fragment(options, fragment, method='GET', post_args=None):
nodeurl = options['node-url'] nodeurl = options['node-url']
if nodeurl.endswith('/'): if nodeurl.endswith('/'):
nodeurl = nodeurl[:-1] nodeurl = nodeurl[:-1]
url = u'%s/%s' % (nodeurl, fragment) url = u'%s/%s' % (nodeurl, fragment)
resp = do_http(method, url) if method == 'POST':
if post_args is None:
raise ValueError("Must pass post_args= for POST method")
body = urllib.urlencode(post_args)
else:
body = ''
if post_args is not None:
raise ValueError("post_args= only valid for POST method")
resp = do_http(method, url, body=body)
if isinstance(resp, BadResponse): if isinstance(resp, BadResponse):
# specifically NOT using format_http_error() here because the # specifically NOT using format_http_error() here because the
# URL is pretty sensitive (we're doing /uri/<key>). # URL is pretty sensitive (we're doing /uri/<key>).
@ -233,8 +241,12 @@ def _get_json_for_fragment(options, fragment, method='GET'):
) )
data = resp.read() data = resp.read()
try:
parsed = simplejson.loads(data) parsed = simplejson.loads(data)
if not parsed: except Exception as e:
print "Failed to parse reply:\n%s" % (data,)
return []
if parsed is None:
raise RuntimeError("No data from '%s'" % (nodeurl,)) raise RuntimeError("No data from '%s'" % (nodeurl,))
return parsed return parsed
@ -339,8 +351,12 @@ def status(options):
token = f.read() token = f.read()
magicdata = _get_json_for_fragment( magicdata = _get_json_for_fragment(
options, options,
'magic_folder?t=json&token=' + token, 'magic_folder?t=json',
method='POST', method='POST',
post_args=dict(
t='json',
token=token,
)
) )
if len(magicdata): if len(magicdata):
uploads = [item for item in magicdata if item['kind'] == 'upload'] uploads = [item for item in magicdata if item['kind'] == 'upload']

View File

@ -395,10 +395,10 @@ class TokenOnlyWebApi(resource.Resource):
provide the "t=" argument to indicate the return-value (the only provide the "t=" argument to indicate the return-value (the only
valid value for this is "json") valid value for this is "json")
Subclasses should override '_render_json' which should process the Subclasses should override 'post_json' which should process the
API call and return a valid JSON object. This will only be called API call and return a string which encodes a valid JSON
if the correct token is present and valid (during renderHTTP object. This will only be called if the correct token is present
processing). and valid (during renderHTTP processing).
""" """
def __init__(self, client): def __init__(self, client):
@ -416,7 +416,7 @@ class TokenOnlyWebApi(resource.Resource):
# argument to work if you passed it as a GET-style argument # argument to work if you passed it as a GET-style argument
token = None token = None
if req.fields and 'token' in req.fields: if req.fields and 'token' in req.fields:
token = req.fields['token'].value[0] token = req.fields['token'].value.strip()
if not token: if not token:
raise WebError("Missing token", http.UNAUTHORIZED) raise WebError("Missing token", http.UNAUTHORIZED)
if not timing_safe_compare(token, self.client.get_auth_token()): if not timing_safe_compare(token, self.client.get_auth_token()):

View File

@ -5,19 +5,19 @@ from twisted.web.server import UnsupportedMethod
from nevow import rend from nevow import rend
from nevow.inevow import IRequest from nevow.inevow import IRequest
from allmydata.web.common import get_arg, WebError from allmydata.web.common import WebError, TokenOnlyWebApi
class MagicFolderWebApi(rend.Page): class MagicFolderWebApi(TokenOnlyWebApi):
""" """
I provide the web-based API for Magic Folder status etc. I provide the web-based API for Magic Folder status etc.
""" """
def __init__(self, client): def __init__(self, client):
super(MagicFolderWebApi, self).__init__(client) TokenOnlyWebApi.__init__(self, client)
self.client = client self.client = client
def _render_json(self, req): def post_json(self, req):
req.setHeader("content-type", "application/json") req.setHeader("content-type", "application/json")
data = [] data = []
@ -44,25 +44,3 @@ class MagicFolderWebApi(rend.Page):
data.append(d) data.append(d)
return simplejson.dumps(data) return simplejson.dumps(data)
def renderHTTP(self, ctx):
req = IRequest(ctx)
t = get_arg(req, "t", None)
if req.method != 'POST':
raise UnsupportedMethod(('POST',))
token = get_arg(req, "token", None)
# XXX need constant-time comparison?
if token is None or token != self.client.get_auth_token():
raise WebError("Missing or invalid token.", 400)
if t is None:
return rend.Page.renderHTTP(self, ctx)
t = t.strip()
if t == 'json':
return self._render_json(req)
raise WebError("'%s' invalid type for 't' arg" % (t,), 400)