mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-10 19:43:01 +00:00
add JupyterHub.admin_access
optionally allow admin users to login to user servers by visiting a special admin-only URL that sets the relevant cookie - disabled by default - an 'access server' button is added to the admin panel, which sets the necessary cookie to log in to the user server
This commit is contained in:
@@ -8,7 +8,7 @@ import json
|
||||
from tornado import gen, web
|
||||
|
||||
from .. import orm
|
||||
from ..utils import admin_only, authenticated_403
|
||||
from ..utils import admin_only
|
||||
from .base import APIHandler
|
||||
|
||||
class BaseUserHandler(APIHandler):
|
||||
@@ -147,8 +147,30 @@ class UserServerAPIHandler(BaseUserHandler):
|
||||
yield self.stop_single_user(user)
|
||||
self.set_status(204)
|
||||
|
||||
class UserAdminAccessAPIHandler(BaseUserHandler):
|
||||
"""Grant admins access to single-user servers
|
||||
|
||||
This handler sets the necessary cookie for an admin to login to a single-user server.
|
||||
"""
|
||||
@admin_only
|
||||
def post(self, name):
|
||||
current = self.get_current_user()
|
||||
self.log.warn("Admin user %s has requested access to %s's server",
|
||||
current.name, name,
|
||||
)
|
||||
if not self.settings.get('admin_access', False):
|
||||
raise web.HTTPError(403, "admin access to user servers disabled")
|
||||
user = self.find_user(name)
|
||||
if user is None:
|
||||
raise web.HTTPError(404)
|
||||
if user.server is None:
|
||||
raise web.HTTPError(400, "%s has no server running" % name)
|
||||
self.set_server_cookie(user)
|
||||
|
||||
|
||||
default_handlers = [
|
||||
(r"/api/users", UserListAPIHandler),
|
||||
(r"/api/users/([^/]+)", UserAPIHandler),
|
||||
(r"/api/users/([^/]+)/server", UserServerAPIHandler),
|
||||
(r"/api/users/([^/]+)/admin-access", UserAdminAccessAPIHandler),
|
||||
]
|
||||
|
@@ -321,6 +321,12 @@ class JupyterHub(Application):
|
||||
db = Any()
|
||||
session_factory = Any()
|
||||
|
||||
admin_access = Bool(False, config=True,
|
||||
help="""Grant admin users permission to access single-user servers.
|
||||
|
||||
Users should be properly informed if this is enabled.
|
||||
"""
|
||||
)
|
||||
admin_users = Set(config=True,
|
||||
help="""set of usernames of admin users
|
||||
|
||||
@@ -708,6 +714,7 @@ class JupyterHub(Application):
|
||||
proxy=self.proxy,
|
||||
hub=self.hub,
|
||||
admin_users=self.admin_users,
|
||||
admin_access=self.admin_access,
|
||||
authenticator=self.authenticator,
|
||||
spawner_class=self.spawner_class,
|
||||
base_url=self.base_url,
|
||||
|
@@ -244,6 +244,7 @@ class BaseHandler(RequestHandler):
|
||||
user = self.get_current_user()
|
||||
return dict(
|
||||
base_url=self.hub.server.base_url,
|
||||
prefix=self.base_url,
|
||||
user=user,
|
||||
login_url=self.settings['login_url'],
|
||||
logout_url=self.settings['logout_url'],
|
||||
|
@@ -48,6 +48,7 @@ class AdminHandler(BaseHandler):
|
||||
html = self.render_template('admin.html',
|
||||
user=self.get_current_user(),
|
||||
users=self.db.query(orm.User),
|
||||
admin_access=self.settings.get('admin_access', False),
|
||||
)
|
||||
self.finish(html)
|
||||
|
||||
|
@@ -1,10 +1,12 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
require(["jquery", "bootstrap", "moment", "jhapi"], function ($, bs, moment, JHAPI) {
|
||||
require(["jquery", "bootstrap", "moment", "jhapi", "utils"], function ($, bs, moment, JHAPI, utils) {
|
||||
"use strict";
|
||||
|
||||
var base_url = window.jhdata.base_url;
|
||||
var prefix = window.jhdata.prefix;
|
||||
|
||||
var api = new JHAPI(base_url);
|
||||
|
||||
var get_row = function (element) {
|
||||
@@ -32,6 +34,23 @@ require(["jquery", "bootstrap", "moment", "jhapi"], function ($, bs, moment, JHA
|
||||
});
|
||||
});
|
||||
|
||||
$(".access-server").click(function () {
|
||||
var el = $(this);
|
||||
var row = get_row(el);
|
||||
var user = row.data('user');
|
||||
var w = window.open();
|
||||
api.admin_access(user, {
|
||||
async: false,
|
||||
success: function () {
|
||||
w.location = utils.url_path_join(prefix, 'user', user);
|
||||
},
|
||||
error: function (xhr, err) {
|
||||
w.close();
|
||||
console.error("Failed to gain access to server", err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(".start-server").click(function () {
|
||||
var el = $(this);
|
||||
var row = get_row(el);
|
||||
|
@@ -100,6 +100,19 @@ define(['jquery', 'utils'], function ($, utils) {
|
||||
);
|
||||
};
|
||||
|
||||
JHAPI.prototype.admin_access = function (user, options) {
|
||||
options = options || {};
|
||||
options = update(options, {
|
||||
type: 'POST',
|
||||
dataType: null,
|
||||
});
|
||||
|
||||
this.api_request(
|
||||
utils.url_path_join('users', user, 'admin-access'),
|
||||
options
|
||||
);
|
||||
};
|
||||
|
||||
JHAPI.prototype.delete_user = function (user, options) {
|
||||
options = options || {};
|
||||
options = update(options, {type: 'DELETE', dataType: null});
|
||||
|
@@ -15,10 +15,13 @@
|
||||
<tr class="user-row" data-user="{{u.name}}" data-admin="{{u.admin}}">
|
||||
<td class="name-col col-sm-2">{{u.name}}</td>
|
||||
<td class="admin-col col-sm-2">{% if u.admin %}admin{% endif %}</td>
|
||||
<td class="time-col col-sm-4">{{u.last_activity.isoformat() + 'Z'}}</td>
|
||||
<td class="server-col col-sm-2 text-center">
|
||||
<td class="time-col col-sm-3">{{u.last_activity.isoformat() + 'Z'}}</td>
|
||||
<td class="server-col col-sm-3 text-center">
|
||||
{% if u.server %}
|
||||
<span class="stop-server btn btn-xs btn-danger">stop server</span>
|
||||
{% if admin_access %}
|
||||
<span class="access-server btn btn-xs btn-success">access server</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="start-server btn btn-xs btn-success">start server</span>
|
||||
{% endif %}
|
||||
|
@@ -54,6 +54,7 @@
|
||||
<script type="text/javascript">
|
||||
window.jhdata = {
|
||||
base_url: "{{base_url}}",
|
||||
prefix: "{{prefix}}",
|
||||
{% if user %}
|
||||
user: "{{user.name}}",
|
||||
{% endif %}
|
||||
|
Reference in New Issue
Block a user