|
2 | 2 | from aiohttp_security import remember, forget |
3 | 3 | from yarl import URL |
4 | 4 |
|
5 | | -from .consts import TEMPLATE_APP_KEY |
| 5 | +from .consts import TEMPLATE_APP_KEY, PROJ_ROOT |
6 | 6 | from .exceptions import JsonValidaitonError |
7 | 7 | from .security import authorize |
8 | 8 | from .utils import json_response, validate_payload, LoginForm |
9 | 9 |
|
10 | 10 |
|
11 | | -__all__ = ['AdminHandler', 'setup_admin_handlers'] |
| 11 | +__all__ = [ |
| 12 | + 'AdminHandler', 'setup_admin_handlers', 'setup_admin_on_rest_handlers', |
| 13 | + 'AdminOnRestHandler', |
| 14 | +] |
12 | 15 |
|
13 | 16 |
|
14 | 17 | class AdminHandler: |
@@ -80,3 +83,78 @@ def setup_admin_handlers(admin, admin_handler, static_folder, admin_conf_path): |
80 | 83 | add_route('DELETE', '/logout', a.logout, name='admin.logout') |
81 | 84 | add_static('/static', path=static_folder, name='admin.static') |
82 | 85 | add_static('/config', path=admin_conf_path, name='admin.config') |
| 86 | + |
| 87 | + |
| 88 | +class AdminOnRestHandler: |
| 89 | + |
| 90 | + template = 'admin_on_rest.jinja2' |
| 91 | + |
| 92 | + def __init__(self, admin, *, resources, loop, schema): |
| 93 | + self._admin = admin |
| 94 | + self._loop = loop |
| 95 | + self.schema = schema |
| 96 | + |
| 97 | + for r in resources: |
| 98 | + r.setup(self._admin, URL('/')) |
| 99 | + self._resources = tuple(resources) |
| 100 | + |
| 101 | + @property |
| 102 | + def resources(self): |
| 103 | + return self._resources |
| 104 | + |
| 105 | + async def index_page(self, request): |
| 106 | + """ |
| 107 | + Return index page with initial state for admin |
| 108 | + """ |
| 109 | + context = {"initial_state": self.schema.to_json()} |
| 110 | + |
| 111 | + return render_template( |
| 112 | + self.template, |
| 113 | + request, |
| 114 | + context, |
| 115 | + app_key=TEMPLATE_APP_KEY, |
| 116 | + ) |
| 117 | + |
| 118 | + async def token(self, request): |
| 119 | + """ |
| 120 | + Validation of user data and generate auth token |
| 121 | + """ |
| 122 | + raw_payload = await request.read() |
| 123 | + data = validate_payload(raw_payload, LoginForm) |
| 124 | + await authorize(request, data['username'], data['password']) |
| 125 | + |
| 126 | + router = request.app.router |
| 127 | + location = router["admin.index"].url_for().human_repr() |
| 128 | + payload = {"location": location} |
| 129 | + response = json_response(payload) |
| 130 | + await remember(request, response, data['username']) |
| 131 | + |
| 132 | + return response |
| 133 | + |
| 134 | + async def logout(self, request): |
| 135 | + """ |
| 136 | + Simple handler for logout |
| 137 | + """ |
| 138 | + if "Authorization" not in request.headers: |
| 139 | + msg = "Auth header is not present, can not destroy token" |
| 140 | + raise JsonValidaitonError(msg) |
| 141 | + |
| 142 | + response = json_response() |
| 143 | + await forget(request, response) |
| 144 | + |
| 145 | + return response |
| 146 | + |
| 147 | + |
| 148 | +def setup_admin_on_rest_handlers(admin, admin_handler): |
| 149 | + """ |
| 150 | + Initialize routes. |
| 151 | + """ |
| 152 | + add_route = admin.router.add_route |
| 153 | + add_static = admin.router.add_static |
| 154 | + static_folder = str(PROJ_ROOT / 'static') |
| 155 | + a = admin_handler |
| 156 | + |
| 157 | + add_route('GET', '', a.index_page, name='admin.index') |
| 158 | + add_route('POST', '/token', a.token, name='admin.token') |
| 159 | + add_static('/static', path=static_folder, name='admin.static') |
| 160 | + add_route('DELETE', '/logout', a.logout, name='admin.logout') |
0 commit comments