Chromium Code Reviews| Index: appengine/chrome_infra_mon_proxy/admin_handler.py |
| diff --git a/appengine/chrome_infra_mon_proxy/admin_handler.py b/appengine/chrome_infra_mon_proxy/admin_handler.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..538a75c8d5d72a631d1518537671146e90845237 |
| --- /dev/null |
| +++ b/appengine/chrome_infra_mon_proxy/admin_handler.py |
| @@ -0,0 +1,128 @@ |
| +# Copyright 2015 The Chromium Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| +import json |
| +import sys |
| +import webapp2 |
| + |
| +from google.appengine.api import users |
| + |
| +import common |
| + |
| +class AdminCommand(object): |
| + """Base class for administrative commands.""" |
| + |
| + def __init__(self, handler): |
| + self._handler = handler |
| + |
| + @property |
| + def request(self): |
| + return self._handler.request |
| + |
| + @property |
| + def response(self): |
| + return self._handler.response |
| + |
| + |
| +class AdminPage(AdminCommand): |
| + """Display the admin page.""" |
| + |
| + def get(self): |
| + self.response.write(open('templates/admin.html').read()) |
| + |
| + def post(self): |
| + self.response.set_status(403) |
| + return |
| + |
| + |
| +def serialize(value): |
|
ghost stip (do not use)
2015/04/14 00:36:42
I'm not entirely sure what these are used for. thi
Sergey Berezin (google)
2015/04/15 01:38:09
Function removed.
|
| + if type(value) is str: |
| + return value |
| + if type(value) is list: |
| + return '\n'.join(value) |
| + if type(value) is dict: |
| + return json.dumps(value) |
| + return 'Unsupported type' |
| + |
| + |
| +def deserialize(value, tp): |
| + if tp is str: |
| + return value |
| + if tp is list: |
| + return [l for l in value.splitlines() if l] |
| + if tp is dict: |
| + return json.loads(value) |
| + raise ValueError('Unsuppored type') |
| + |
| + |
| +class SetCredentials(AdminCommand): |
| + """Save new credentials for the Monacq endpoint.""" |
| + |
| + # TODO(sergeyberezin): move this and (de)serialize funcs to common.py. |
| + fields = { |
| + 'message': str, |
| + 'url': str, |
| + 'credentials': dict, |
| + 'scopes': list, |
| + 'headers': dict, |
| + } |
| + |
| + def get(self): |
| + params = {f: serialize(tp()) for f, tp in self.fields.iteritems()} |
| + data = common.MonAcqData.get_by_id(common.CREDENTIALS_KEY) |
| + if data: |
| + params.update({ |
| + f: serialize(self.fields[f](v)) for f, v in data.to_dict().items()}) |
| + self.response.headers["Content-Type"] = 'text/html' |
| + self.response.write(open('templates/set_credentials.html').read() % params) |
|
ghost stip (do not use)
2015/04/14 00:36:41
you should use jinja
Sergey Berezin (google)
2015/04/15 01:38:09
Done.
|
| + |
| + def post(self): |
| + params = {f: serialize(tp()) for f, tp in self.fields.iteritems()} |
| + data = common.MonAcqData.get_or_insert(common.CREDENTIALS_KEY) |
| + params.update({f: serialize(v) for f, v in data.to_dict().iteritems()}) |
| + |
| + updated_fields = [] |
| + failed_fields = [] |
| + for field, tp in self.fields.iteritems(): |
| + if not self.request.get(field): |
| + continue |
| + try: |
| + setattr(data, field, deserialize(self.request.get(field), tp)) |
| + updated_fields.append(field) |
| + except ValueError: |
| + failed_fields.append(field) |
| + params[field] = self.request.get(field) |
| + |
| + if failed_fields: |
| + self.response.headers["Content-Type"] = 'text/html' |
|
ghost stip (do not use)
2015/04/14 00:36:42
I think this is set by default?
Sergey Berezin (google)
2015/04/15 01:38:09
True. And now irrelevant (jinja!)
|
| + params['message'] = 'Failed to update %s. Please try again.' % ( |
| + ', '.join(failed_fields)) |
| + self.response.out.write( |
| + open('templates/set_credentials.html').read() % params) |
| + return |
| + if updated_fields: |
| + data.put() |
| + params['message'] = 'Updated %s.' % ', '.join(updated_fields) |
| + self.response.headers["Content-Type"] = 'text/html' |
| + self.response.out.write( |
| + open('templates/set_credentials.html').read() % params) |
|
ghost stip (do not use)
2015/04/14 00:36:42
again, jinja. from what I'm reading, you can repla
Sergey Berezin (google)
2015/04/15 01:38:09
Done. Thanks for the pointers!
|
| + |
| + |
| +commands = { |
| + '': AdminPage, |
| + 'set-credentials': SetCredentials, |
| +} |
| + |
| +class AdminDispatch(webapp2.RequestHandler): |
|
ghost stip (do not use)
2015/04/14 00:36:41
I think you can remove lines 112 - 128 if you just
Sergey Berezin (google)
2015/04/15 01:38:09
First, I'd really like to switch to auth groups he
|
| + def get(self, command): |
| + if not users.is_current_user_admin(): |
| + self.redirect(users.create_login_url(self.request.url)) |
| + return |
| + commands[command](self).get() |
| + |
| + def post(self, command): |
| + if not users.is_current_user_admin(): |
| + self.response.set_status(403) |
| + return |
| + commands[command](self).post() |