add 'admin-ui' scope for access to the admin ui

This commit is contained in:
Min RK
2022-04-29 11:45:58 +02:00
parent ec2c90c73f
commit debac715bf
6 changed files with 25 additions and 8 deletions

View File

@@ -1391,6 +1391,9 @@ components:
inherit: inherit:
Everything that the token-owning entity can access _(metascope Everything that the token-owning entity can access _(metascope
for tokens)_ for tokens)_
admin-ui:
Access the admin page. Permission to take actions via the admin
page granted separately.
admin:users: admin:users:
Read, write, create and delete users and their authentication Read, write, create and delete users and their authentication
state, not including their servers or tokens. state, not including their servers or tokens.

View File

@@ -454,15 +454,14 @@ class AdminHandler(BaseHandler):
@web.authenticated @web.authenticated
# stacked decorators: all scopes must be present # stacked decorators: all scopes must be present
# note: keep in sync with admin link condition in page.html # note: keep in sync with admin link condition in page.html
@needs_scope('admin:users') @needs_scope('admin-ui')
@needs_scope('admin:servers')
async def get(self): async def get(self):
auth_state = await self.current_user.get_auth_state() auth_state = await self.current_user.get_auth_state()
html = await self.render_template( html = await self.render_template(
'admin.html', 'admin.html',
current_user=self.current_user, current_user=self.current_user,
auth_state=auth_state, auth_state=auth_state,
admin_access=self.settings.get('admin_access', False), admin_access=True,
allow_named_servers=self.allow_named_servers, allow_named_servers=self.allow_named_servers,
named_server_limit_per_user=self.named_server_limit_per_user, named_server_limit_per_user=self.named_server_limit_per_user,
server_version=f'{__version__} {self.version_hash}', server_version=f'{__version__} {self.version_hash}',

View File

@@ -31,6 +31,7 @@ def get_default_roles():
'name': 'admin', 'name': 'admin',
'description': 'Elevated privileges (can do anything)', 'description': 'Elevated privileges (can do anything)',
'scopes': [ 'scopes': [
'admin-ui',
'admin:users', 'admin:users',
'admin:servers', 'admin:servers',
'tokens', 'tokens',

View File

@@ -42,6 +42,10 @@ scope_definitions = {
'description': 'Anything you have access to', 'description': 'Anything you have access to',
'doc_description': 'Everything that the token-owning entity can access _(metascope for tokens)_', 'doc_description': 'Everything that the token-owning entity can access _(metascope for tokens)_',
}, },
'admin-ui': {
'description': 'Access the admin page.',
'doc_description': 'Access the admin page. Permission to take actions via the admin page granted separately.',
},
'admin:users': { 'admin:users': {
'description': 'Read, write, create and delete users and their authentication state, not including their servers or tokens.', 'description': 'Read, write, create and delete users and their authentication state, not including their servers or tokens.',
'subscopes': ['admin:auth_state', 'users', 'read:roles:users', 'delete:users'], 'subscopes': ['admin:auth_state', 'users', 'read:roles:users', 'delete:users'],

View File

@@ -1105,17 +1105,27 @@ async def test_bad_oauth_get(app, params):
[ [
(["users"], False), (["users"], False),
(["admin:users"], False), (["admin:users"], False),
(["users", "admin:users", "admin:servers"], True), (["users", "admin:users", "admin:servers"], False),
(["admin-ui"], True),
], ],
) )
async def test_admin_page_access(app, scopes, has_access, create_user_with_scopes): async def test_admin_page_access(app, scopes, has_access, create_user_with_scopes):
user = create_user_with_scopes(*scopes) user = create_user_with_scopes(*scopes)
cookies = await app.login_user(user.name) cookies = await app.login_user(user.name)
r = await get_page("/admin", app, cookies=cookies) home_resp = await get_page("/home", app, cookies=cookies)
admin_resp = await get_page("/admin", app, cookies=cookies)
assert home_resp.status_code == 200
soup = BeautifulSoup(home_resp.text, "html.parser")
nav = soup.find("div", id="thenavbar")
links = [a["href"] for a in nav.find_all("a")]
admin_url = app.base_url + "hub/admin"
if has_access: if has_access:
assert r.status_code == 200 assert admin_resp.status_code == 200
assert admin_url in links
else: else:
assert r.status_code == 403 assert admin_resp.status_code == 403
assert admin_url not in links
async def test_oauth_page_scope_appearance( async def test_oauth_page_scope_appearance(

View File

@@ -122,7 +122,7 @@
{% block nav_bar_left_items %} {% block nav_bar_left_items %}
<li><a href="{{base_url}}home">Home</a></li> <li><a href="{{base_url}}home">Home</a></li>
<li><a href="{{base_url}}token">Token</a></li> <li><a href="{{base_url}}token">Token</a></li>
{% if 'admin:users' in parsed_scopes and 'admin:servers' in parsed_scopes %} {% if 'admin-ui' in parsed_scopes %}
<li><a href="{{base_url}}admin">Admin</a></li> <li><a href="{{base_url}}admin">Admin</a></li>
{% endif %} {% endif %}
{% if services %} {% if services %}