Skip to content

Commit

Permalink
Merge pull request #3743 from minrk/noro
Browse files Browse the repository at this point in the history
remove notebook read-only view

it is largely broken, and had problematic security issues.
  • Loading branch information
Carreau committed Jul 25, 2013
2 parents bd4cc05 + 961067e commit c2464fa
Show file tree
Hide file tree
Showing 14 changed files with 26 additions and 105 deletions.
39 changes: 2 additions & 37 deletions IPython/html/base/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,33 +88,6 @@ def _execute(self, transforms, *args, **kwargs):
websocket.WebSocketHandler._execute = _execute
del _execute

#-----------------------------------------------------------------------------
# Decorator for disabling read-only handlers
#-----------------------------------------------------------------------------

@decorator
def not_if_readonly(f, self, *args, **kwargs):
if self.settings.get('read_only', False):
raise web.HTTPError(403, "Notebook server is read-only")
else:
return f(self, *args, **kwargs)

@decorator
def authenticate_unless_readonly(f, self, *args, **kwargs):
"""authenticate this page *unless* readonly view is active.
In read-only mode, the notebook list and print view should
be accessible without authentication.
"""

@web.authenticated
def auth_f(self, *args, **kwargs):
return f(self, *args, **kwargs)

if self.settings.get('read_only', False):
return f(self, *args, **kwargs)
else:
return auth_f(self, *args, **kwargs)

#-----------------------------------------------------------------------------
# Top-level handlers
Expand All @@ -141,7 +114,7 @@ def get_current_user(self):
if user_id is None:
# prevent extra Invalid cookie sig warnings:
self.clear_login_cookie()
if not self.read_only and not self.login_available:
if not self.login_available:
user_id = 'anonymous'
return user_id

Expand Down Expand Up @@ -175,13 +148,6 @@ def login_available(self):
"""
return bool(self.settings.get('password', ''))

@property
def read_only(self):
"""Is the notebook read-only?
"""
return self.settings.get('read_only', False)


class IPythonHandler(AuthenticatedHandler):
"""IPython-specific extensions to authenticated handling
Expand Down Expand Up @@ -269,7 +235,6 @@ def template_namespace(self):
return dict(
base_project_url=self.base_project_url,
base_kernel_url=self.base_kernel_url,
read_only=self.read_only,
logged_in=self.logged_in,
login_available=self.login_available,
use_less=self.use_less,
Expand All @@ -278,7 +243,7 @@ def template_namespace(self):
class AuthenticatedFileHandler(IPythonHandler, web.StaticFileHandler):
"""static files should only be accessible when logged in"""

@authenticate_unless_readonly
@web.authenticated
def get(self, path):
return web.StaticFileHandler.get(self, path)

Expand Down
6 changes: 3 additions & 3 deletions IPython/html/notebook/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from tornado import web
HTTPError = web.HTTPError

from ..base.handlers import IPythonHandler, authenticate_unless_readonly
from ..base.handlers import IPythonHandler
from ..utils import url_path_join

#-----------------------------------------------------------------------------
Expand All @@ -38,7 +38,7 @@ def get(self):

class NamedNotebookHandler(IPythonHandler):

@authenticate_unless_readonly
@web.authenticated
def get(self, notebook_id):
nbm = self.notebook_manager
if not nbm.notebook_exists(notebook_id):
Expand All @@ -54,7 +54,7 @@ def get(self, notebook_id):

class NotebookRedirectHandler(IPythonHandler):

@authenticate_unless_readonly
@web.authenticated
def get(self, notebook_name):
# strip trailing .ipynb:
notebook_name = os.path.splitext(notebook_name)[0]
Expand Down
21 changes: 2 additions & 19 deletions IPython/html/notebookapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ def init_settings(self, ipython_app, kernel_manager, notebook_manager,
# authentication
cookie_secret=ipython_app.cookie_secret,
login_url=url_path_join(base_project_url,'/login'),
read_only=ipython_app.read_only,
password=ipython_app.password,

# managers
Expand Down Expand Up @@ -227,18 +226,6 @@ def init_handlers(self, settings):
When disabled, equations etc. will appear as their untransformed TeX source.
"""
)
flags['read-only'] = (
{'NotebookApp' : {'read_only' : True}},
"""Allow read-only access to notebooks.
When using a password to protect the notebook server, this flag
allows unauthenticated clients to view the notebook list, and
individual notebooks, but not edit them, start kernels, or run
code.
If no password is set, the server will be entirely read-only.
"""
)

# Add notebook manager flags
flags.update(boolean_flag('script', 'FileNotebookManager.save_script',
Expand All @@ -248,7 +235,7 @@ def init_handlers(self, settings):
# the flags that are specific to the frontend
# these must be scrubbed before being passed to the kernel,
# or it will raise an error on unrecognized flags
notebook_flags = ['no-browser', 'no-mathjax', 'read-only', 'script', 'no-script']
notebook_flags = ['no-browser', 'no-mathjax', 'script', 'no-script']

aliases = dict(kernel_aliases)

Expand Down Expand Up @@ -369,10 +356,6 @@ def _cookie_secret_default(self):
BROWSER environment variable to override it.
""")

read_only = Bool(False, config=True,
help="Whether to prevent editing/execution of notebooks."
)

use_less = Bool(False, config=True,
help="""Wether to use Browser Side less-css parsing
instead of compiled css version in templates that allows
Expand Down Expand Up @@ -554,7 +537,7 @@ def init_webapp(self):
if ssl_options is None:
self.log.critical(warning + " and not using encryption. This "
"is not recommended.")
if not self.password and not self.read_only:
if not self.password:
self.log.critical(warning + " and not using authentication. "
"This is highly insecure and not recommended.")
success = None
Expand Down
6 changes: 3 additions & 3 deletions IPython/html/services/notebooks/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@

from IPython.utils.jsonutil import date_default

from ...base.handlers import IPythonHandler, authenticate_unless_readonly
from ...base.handlers import IPythonHandler

#-----------------------------------------------------------------------------
# Notebook web service handlers
#-----------------------------------------------------------------------------

class NotebookRootHandler(IPythonHandler):

@authenticate_unless_readonly
@web.authenticated
def get(self):
nbm = self.notebook_manager
km = self.kernel_manager
Expand All @@ -57,7 +57,7 @@ class NotebookHandler(IPythonHandler):

SUPPORTED_METHODS = ('GET', 'PUT', 'DELETE')

@authenticate_unless_readonly
@web.authenticated
def get(self, notebook_id):
nbm = self.notebook_manager
format = self.get_argument('format', default='json')
Expand Down
4 changes: 0 additions & 4 deletions IPython/html/static/notebook/js/codecell.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,6 @@ var IPython = (function (IPython) {
*/
CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {

if (this.read_only){
return false;
}

var that = this;
// whatever key is pressed, first, cancel the tooltip request before
// they are sent, and remove tooltip if any, except for tab again
Expand Down
12 changes: 1 addition & 11 deletions IPython/html/static/notebook/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ function (marked) {

IPython.mathjaxutils.init();

IPython.read_only = $('body').data('readOnly') === 'True';
$('#ipython-main-app').addClass('border-box-sizing');
$('div#notebook_panel').addClass('border-box-sizing');

Expand All @@ -54,7 +53,7 @@ function (marked) {
IPython.pager = new IPython.Pager('div#pager', 'div#pager_splitter');
IPython.quick_help = new IPython.QuickHelp();
IPython.login_widget = new IPython.LoginWidget('span#login_widget',{baseProjectUrl:baseProjectUrl});
IPython.notebook = new IPython.Notebook('div#notebook',{baseProjectUrl:baseProjectUrl, read_only:IPython.read_only});
IPython.notebook = new IPython.Notebook('div#notebook',{baseProjectUrl:baseProjectUrl});
IPython.save_widget = new IPython.SaveWidget('span#save_widget');
IPython.menubar = new IPython.MenuBar('#menubar',{baseProjectUrl:baseProjectUrl})
IPython.toolbar = new IPython.MainToolBar('#maintoolbar-container')
Expand All @@ -75,15 +74,6 @@ function (marked) {
}
$('#fonttest').remove();

if(IPython.read_only){
// hide various elements from read-only view
$('div#pager').remove();
$('div#pager_splitter').remove();

// set the notebook name field as not modifiable
$('#notebook_name').attr('disabled','disabled')
}

IPython.page.show();

IPython.layout_manager.do_resize();
Expand Down
15 changes: 5 additions & 10 deletions IPython/html/static/notebook/js/notebook.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ var IPython = (function (IPython) {
var Notebook = function (selector, options) {
var options = options || {};
this._baseProjectUrl = options.baseProjectUrl;
this.read_only = options.read_only || IPython.read_only;

this.element = $(selector);
this.element.scroll();
Expand Down Expand Up @@ -91,7 +90,6 @@ var IPython = (function (IPython) {
this.container = $("<div/>").addClass("container").attr("id", "notebook-container");
var end_space = $('<div/>').addClass('end_space');
end_space.dblclick(function (e) {
if (that.read_only) return;
var ncells = that.ncells();
that.insert_cell_below('code',ncells-1);
});
Expand Down Expand Up @@ -138,8 +136,6 @@ var IPython = (function (IPython) {


$(document).keydown(function (event) {
// console.log(event);
if (that.read_only) return true;

// Save (CTRL+S) or (AppleKey+S)
//metaKey = applekey on mac
Expand Down Expand Up @@ -366,7 +362,7 @@ var IPython = (function (IPython) {
}
// if we are autosaving, trigger an autosave on nav-away.
// still warn, because if we don't the autosave may fail.
if (that.dirty && ! that.read_only) {
if (that.dirty) {
if ( that.autosave_interval ) {
// schedule autosave in a timeout
// this gives you a chance to forcefully discard changes
Expand Down Expand Up @@ -1785,11 +1781,10 @@ var IPython = (function (IPython) {

// Create the kernel after the notebook is completely loaded to prevent
// code execution upon loading, which is a security risk.
if (! this.read_only) {
this.start_kernel();
// load our checkpoint list
IPython.notebook.list_checkpoints();
}
this.start_kernel();
// load our checkpoint list
IPython.notebook.list_checkpoints();

$([IPython.events]).trigger('notebook_loaded.Notebook');
};

Expand Down
1 change: 0 additions & 1 deletion IPython/html/static/notebook/js/textcell.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ var IPython = (function (IPython) {
* @method edit
*/
TextCell.prototype.edit = function () {
if ( this.read_only ) return;
if (this.rendered === true) {
var text_cell = this.element;
var output = text_cell.find("div.text_cell_render");
Expand Down
1 change: 0 additions & 1 deletion IPython/html/static/tree/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ $(document).ready(function () {
window.open($('body').data('baseProjectUrl')+'new');
});

IPython.read_only = $('body').data('readOnly') === 'True';
IPython.notebook_list = new IPython.NotebookList('#notebook_list');
IPython.cluster_list = new IPython.ClusterList('#cluster_list');
IPython.login_widget = new IPython.LoginWidget('#login_widget');
Expand Down
15 changes: 5 additions & 10 deletions IPython/html/static/tree/js/notebooklist.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ var IPython = (function (IPython) {


NotebookList.prototype.bind_events = function () {
if (IPython.read_only){
return;
}
var that = this;
$('#refresh_notebook_list').click(function () {
that.load_list();
Expand Down Expand Up @@ -129,13 +126,11 @@ var IPython = (function (IPython) {
var kernel = data[i].kernel_id;
var item = this.new_notebook_item(i);
this.add_link(notebook_id, nbname, item);
if (!IPython.read_only){
// hide delete buttons when readonly
if(kernel == null){
this.add_delete_button(item);
} else {
this.add_shutdown_button(item,kernel);
}
// hide delete buttons when readonly
if(kernel == null){
this.add_delete_button(item);
} else {
this.add_shutdown_button(item,kernel);
}
};
};
Expand Down
2 changes: 1 addition & 1 deletion IPython/html/templates/logout.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
{% endfor %}
{% endif %}

{% if read_only or not login_available %}
{% if not login_available %}
Proceed to the <a href="{{base_project_url}}">dashboard</a>.
{% else %}
Proceed to the <a href="{{base_project_url}}login">login page</a>.
Expand Down
1 change: 0 additions & 1 deletion IPython/html/templates/notebook.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
data-project={{project}}
data-base-project-url={{base_project_url}}
data-base-kernel-url={{base_kernel_url}}
data-read-only={{read_only and not logged_in}}
data-notebook-id={{notebook_id}}
class="notebook_app"

Expand Down
3 changes: 1 addition & 2 deletions IPython/html/templates/tree.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
data-project={{project}}
data-base-project-url={{base_project_url}}
data-base-kernel-url={{base_kernel_url}}
data-read-only={{read_only}}

{% endblock %}

Expand All @@ -30,7 +29,7 @@

<div class="tab-content">
<div id="notebooks" class="tab-pane active">
{% if logged_in or not read_only %}
{% if logged_in %}
<div id="notebook_toolbar">
<form id='alternate_upload' class='alternate_upload' >
<span id="drag_info" style="position:absolute" >
Expand Down
5 changes: 3 additions & 2 deletions IPython/html/tree/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
# Imports
#-----------------------------------------------------------------------------

from ..base.handlers import IPythonHandler, authenticate_unless_readonly
from tornado import web
from ..base.handlers import IPythonHandler

#-----------------------------------------------------------------------------
# Handlers
Expand All @@ -25,7 +26,7 @@

class ProjectDashboardHandler(IPythonHandler):

@authenticate_unless_readonly
@web.authenticated
def get(self):
self.write(self.render_template('tree.html',
project=self.project,
Expand Down

0 comments on commit c2464fa

Please sign in to comment.