Skip to content

Commit

Permalink
Control access by roles
Browse files Browse the repository at this point in the history
  • Loading branch information
trungleduc committed Mar 13, 2024
1 parent e84432e commit f75fdde
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 17 deletions.
14 changes: 6 additions & 8 deletions jupyterhub_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
and overrides some of the default values from the plugin.
"""

import getpass

from jupyterhub.auth import DummyAuthenticator
from tljh.configurer import apply_config, load_config
from tljh_repo2docker import tljh_custom_jupyterhub_config
Expand All @@ -31,8 +29,6 @@

c.JupyterHub.authenticator_class = DummyAuthenticator

user = getpass.getuser()
c.Authenticator.admin_users = {user, "alice"}
c.JupyterHub.allow_named_servers = True
c.JupyterHub.ip = "0.0.0.0"

Expand All @@ -55,19 +51,21 @@
]
)


c.JupyterHub.load_roles = [
{
"description": "Role for tljh_repo2docker service",
"name": "tljh_repo2docker_role",
"name": "tljh-repo2docker-service",
"scopes": ["read:users", "read:servers", "read:roles:users"],
"services": ["tljh_repo2docker"],
},
{"name": "tljh-repo2docker-service-admin", "users": ["alice"]},
{
"name": "env-user",
"name": "user",
"scopes": [
"self",
# access to the env page
"access:services"
"access:services!service=tljh_repo2docker",
],
"users": ["trung"],
},
]
2 changes: 2 additions & 0 deletions tljh_repo2docker/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
# See: https://docs.docker.com/config/containers/resource_constraints/#limit-a-containers-access-to-memory#configure-the-default-cfs-scheduler
CPU_PERIOD = 100_000

TLJH_R2D_ADMIN_ROLE = 'tljh-repo2docker-service-admin'


class SpawnerMixin(Configurable):
"""
Expand Down
22 changes: 17 additions & 5 deletions tljh_repo2docker/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
from jupyterhub.services.auth import HubOAuthenticated
from jupyterhub.utils import url_path_join
from tornado import web
from jupyterhub.scopes import needs_scope

from tljh_repo2docker import TLJH_R2D_ADMIN_ROLE

from .model import UserModel


Expand Down Expand Up @@ -35,8 +37,16 @@ async def fetch_user(self) -> UserModel:
user_model: dict = response.json()
user_model.setdefault("name", user["name"])
user_model.setdefault("servers", {})
user_model.setdefault("roles", [])
user_model.setdefault("admin", False)

if not user_model["admin"]:
if (
"admin" in user_model["roles"]
or TLJH_R2D_ADMIN_ROLE in user_model["roles"]
):
user_model["admin"] = True

return UserModel.from_dict(user_model)

def get_template(self, name: str) -> Template:
Expand All @@ -48,23 +58,25 @@ def get_template(self, name: str) -> Template:
"""
return self.settings["jinja2_env"].get_template(name)

def render_template(self, name: str, **kwargs) -> str:
async def render_template(self, name: str, **kwargs) -> str:
"""Render the given template with the provided arguments
Args:
name: Template name
**kwargs: Template arguments
Returns:
The generated template
"""
user = self.current_user
user = await self.fetch_user()
base_url = self.settings.get("base_url", "/")
template_ns = dict(
service_prefix=self.settings.get("service_prefix", "/"),
hub_prefix=self.settings.get("hub_prefix", "/"),
base_url=self.settings.get("base_url", "/"),
base_url=base_url,
logout_url=self.settings.get("logout_url", url_path_join(base_url, 'logout')),
static_url=self.static_url,
xsrf_token=self.xsrf_token.decode("ascii"),
user=user,
admin_access=user["admin"],
admin_access=user.admin,
)
template_ns.update(kwargs)
template = self.get_template(name)
Expand Down
5 changes: 3 additions & 2 deletions tljh_repo2docker/environments.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from inspect import isawaitable

from tornado import web

from .base import BaseHandler
from .docker import list_containers, list_images

Expand All @@ -12,9 +13,9 @@ class EnvironmentsHandler(BaseHandler):

@web.authenticated
async def get(self):
user = self.current_user
user = await self.fetch_user()

if not user["admin"]:
if not user.admin:
raise web.HTTPError(status_code=404, reason="Unauthorized.")
images = await list_images()
containers = await list_containers()
Expand Down
2 changes: 2 additions & 0 deletions tljh_repo2docker/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class UserModel:
name: str
admin: bool
servers: dict
roles: list

@classmethod
def from_dict(self, kwargs_dict: dict):
Expand All @@ -30,3 +31,4 @@ def all_spawners(self) -> list:
}
)
return sp

4 changes: 2 additions & 2 deletions tljh_repo2docker/templates/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
base_url: "{{base_url}}",
hub_prefix: "{{hub_prefix}}",
{% if user %}
user: "{{ user['name'] | safe }}",
user: "{{ user.name | safe }}",
{% endif %}
{% if admin_access %}
admin_access: true,
Expand Down Expand Up @@ -86,7 +86,7 @@
{% block login_widget %}
<span id="login_widget">
{% if user %}
<p class="navbar-text">{{user['name']}}</p>
<p class="navbar-text">{{user.name}}</p>
<a
id="logout"
role="button"
Expand Down

0 comments on commit f75fdde

Please sign in to comment.