Show More
@@ -88,33 +88,6 b' if tornado.version_info <= (2,1,1):' | |||||
88 | websocket.WebSocketHandler._execute = _execute |
|
88 | websocket.WebSocketHandler._execute = _execute | |
89 | del _execute |
|
89 | del _execute | |
90 |
|
90 | |||
91 | #----------------------------------------------------------------------------- |
|
|||
92 | # Decorator for disabling read-only handlers |
|
|||
93 | #----------------------------------------------------------------------------- |
|
|||
94 |
|
||||
95 | @decorator |
|
|||
96 | def not_if_readonly(f, self, *args, **kwargs): |
|
|||
97 | if self.settings.get('read_only', False): |
|
|||
98 | raise web.HTTPError(403, "Notebook server is read-only") |
|
|||
99 | else: |
|
|||
100 | return f(self, *args, **kwargs) |
|
|||
101 |
|
||||
102 | @decorator |
|
|||
103 | def authenticate_unless_readonly(f, self, *args, **kwargs): |
|
|||
104 | """authenticate this page *unless* readonly view is active. |
|
|||
105 |
|
||||
106 | In read-only mode, the notebook list and print view should |
|
|||
107 | be accessible without authentication. |
|
|||
108 | """ |
|
|||
109 |
|
||||
110 | @web.authenticated |
|
|||
111 | def auth_f(self, *args, **kwargs): |
|
|||
112 | return f(self, *args, **kwargs) |
|
|||
113 |
|
||||
114 | if self.settings.get('read_only', False): |
|
|||
115 | return f(self, *args, **kwargs) |
|
|||
116 | else: |
|
|||
117 | return auth_f(self, *args, **kwargs) |
|
|||
118 |
|
91 | |||
119 | #----------------------------------------------------------------------------- |
|
92 | #----------------------------------------------------------------------------- | |
120 | # Top-level handlers |
|
93 | # Top-level handlers | |
@@ -141,7 +114,7 b' class AuthenticatedHandler(RequestHandler):' | |||||
141 | if user_id is None: |
|
114 | if user_id is None: | |
142 | # prevent extra Invalid cookie sig warnings: |
|
115 | # prevent extra Invalid cookie sig warnings: | |
143 | self.clear_login_cookie() |
|
116 | self.clear_login_cookie() | |
144 |
if not self. |
|
117 | if not self.login_available: | |
145 | user_id = 'anonymous' |
|
118 | user_id = 'anonymous' | |
146 | return user_id |
|
119 | return user_id | |
147 |
|
120 | |||
@@ -175,13 +148,6 b' class AuthenticatedHandler(RequestHandler):' | |||||
175 | """ |
|
148 | """ | |
176 | return bool(self.settings.get('password', '')) |
|
149 | return bool(self.settings.get('password', '')) | |
177 |
|
150 | |||
178 | @property |
|
|||
179 | def read_only(self): |
|
|||
180 | """Is the notebook read-only? |
|
|||
181 |
|
||||
182 | """ |
|
|||
183 | return self.settings.get('read_only', False) |
|
|||
184 |
|
||||
185 |
|
151 | |||
186 | class IPythonHandler(AuthenticatedHandler): |
|
152 | class IPythonHandler(AuthenticatedHandler): | |
187 | """IPython-specific extensions to authenticated handling |
|
153 | """IPython-specific extensions to authenticated handling | |
@@ -269,7 +235,6 b' class IPythonHandler(AuthenticatedHandler):' | |||||
269 | return dict( |
|
235 | return dict( | |
270 | base_project_url=self.base_project_url, |
|
236 | base_project_url=self.base_project_url, | |
271 | base_kernel_url=self.base_kernel_url, |
|
237 | base_kernel_url=self.base_kernel_url, | |
272 | read_only=self.read_only, |
|
|||
273 | logged_in=self.logged_in, |
|
238 | logged_in=self.logged_in, | |
274 | login_available=self.login_available, |
|
239 | login_available=self.login_available, | |
275 | use_less=self.use_less, |
|
240 | use_less=self.use_less, | |
@@ -278,7 +243,7 b' class IPythonHandler(AuthenticatedHandler):' | |||||
278 | class AuthenticatedFileHandler(IPythonHandler, web.StaticFileHandler): |
|
243 | class AuthenticatedFileHandler(IPythonHandler, web.StaticFileHandler): | |
279 | """static files should only be accessible when logged in""" |
|
244 | """static files should only be accessible when logged in""" | |
280 |
|
245 | |||
281 |
@authenticate |
|
246 | @web.authenticated | |
282 | def get(self, path): |
|
247 | def get(self, path): | |
283 | return web.StaticFileHandler.get(self, path) |
|
248 | return web.StaticFileHandler.get(self, path) | |
284 |
|
249 |
@@ -20,7 +20,7 b' import os' | |||||
20 | from tornado import web |
|
20 | from tornado import web | |
21 | HTTPError = web.HTTPError |
|
21 | HTTPError = web.HTTPError | |
22 |
|
22 | |||
23 |
from ..base.handlers import IPythonHandler |
|
23 | from ..base.handlers import IPythonHandler | |
24 | from ..utils import url_path_join |
|
24 | from ..utils import url_path_join | |
25 |
|
25 | |||
26 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
@@ -38,7 +38,7 b' class NewHandler(IPythonHandler):' | |||||
38 |
|
38 | |||
39 | class NamedNotebookHandler(IPythonHandler): |
|
39 | class NamedNotebookHandler(IPythonHandler): | |
40 |
|
40 | |||
41 |
@authenticate |
|
41 | @web.authenticated | |
42 | def get(self, notebook_id): |
|
42 | def get(self, notebook_id): | |
43 | nbm = self.notebook_manager |
|
43 | nbm = self.notebook_manager | |
44 | if not nbm.notebook_exists(notebook_id): |
|
44 | if not nbm.notebook_exists(notebook_id): | |
@@ -54,7 +54,7 b' class NamedNotebookHandler(IPythonHandler):' | |||||
54 |
|
54 | |||
55 | class NotebookRedirectHandler(IPythonHandler): |
|
55 | class NotebookRedirectHandler(IPythonHandler): | |
56 |
|
56 | |||
57 |
@authenticate |
|
57 | @web.authenticated | |
58 | def get(self, notebook_name): |
|
58 | def get(self, notebook_name): | |
59 | # strip trailing .ipynb: |
|
59 | # strip trailing .ipynb: | |
60 | notebook_name = os.path.splitext(notebook_name)[0] |
|
60 | notebook_name = os.path.splitext(notebook_name)[0] |
@@ -164,7 +164,6 b' class NotebookWebApplication(web.Application):' | |||||
164 | # authentication |
|
164 | # authentication | |
165 | cookie_secret=ipython_app.cookie_secret, |
|
165 | cookie_secret=ipython_app.cookie_secret, | |
166 | login_url=url_path_join(base_project_url,'/login'), |
|
166 | login_url=url_path_join(base_project_url,'/login'), | |
167 | read_only=ipython_app.read_only, |
|
|||
168 | password=ipython_app.password, |
|
167 | password=ipython_app.password, | |
169 |
|
168 | |||
170 | # managers |
|
169 | # managers | |
@@ -227,18 +226,6 b" flags['no-mathjax']=(" | |||||
227 | When disabled, equations etc. will appear as their untransformed TeX source. |
|
226 | When disabled, equations etc. will appear as their untransformed TeX source. | |
228 | """ |
|
227 | """ | |
229 | ) |
|
228 | ) | |
230 | flags['read-only'] = ( |
|
|||
231 | {'NotebookApp' : {'read_only' : True}}, |
|
|||
232 | """Allow read-only access to notebooks. |
|
|||
233 |
|
||||
234 | When using a password to protect the notebook server, this flag |
|
|||
235 | allows unauthenticated clients to view the notebook list, and |
|
|||
236 | individual notebooks, but not edit them, start kernels, or run |
|
|||
237 | code. |
|
|||
238 |
|
||||
239 | If no password is set, the server will be entirely read-only. |
|
|||
240 | """ |
|
|||
241 | ) |
|
|||
242 |
|
229 | |||
243 | # Add notebook manager flags |
|
230 | # Add notebook manager flags | |
244 | flags.update(boolean_flag('script', 'FileNotebookManager.save_script', |
|
231 | flags.update(boolean_flag('script', 'FileNotebookManager.save_script', | |
@@ -248,7 +235,7 b" flags.update(boolean_flag('script', 'FileNotebookManager.save_script'," | |||||
248 | # the flags that are specific to the frontend |
|
235 | # the flags that are specific to the frontend | |
249 | # these must be scrubbed before being passed to the kernel, |
|
236 | # these must be scrubbed before being passed to the kernel, | |
250 | # or it will raise an error on unrecognized flags |
|
237 | # or it will raise an error on unrecognized flags | |
251 |
notebook_flags = ['no-browser', 'no-mathjax', ' |
|
238 | notebook_flags = ['no-browser', 'no-mathjax', 'script', 'no-script'] | |
252 |
|
239 | |||
253 | aliases = dict(kernel_aliases) |
|
240 | aliases = dict(kernel_aliases) | |
254 |
|
241 | |||
@@ -369,10 +356,6 b' class NotebookApp(BaseIPythonApplication):' | |||||
369 | BROWSER environment variable to override it. |
|
356 | BROWSER environment variable to override it. | |
370 | """) |
|
357 | """) | |
371 |
|
358 | |||
372 | read_only = Bool(False, config=True, |
|
|||
373 | help="Whether to prevent editing/execution of notebooks." |
|
|||
374 | ) |
|
|||
375 |
|
||||
376 | use_less = Bool(False, config=True, |
|
359 | use_less = Bool(False, config=True, | |
377 | help="""Wether to use Browser Side less-css parsing |
|
360 | help="""Wether to use Browser Side less-css parsing | |
378 | instead of compiled css version in templates that allows |
|
361 | instead of compiled css version in templates that allows | |
@@ -554,7 +537,7 b' class NotebookApp(BaseIPythonApplication):' | |||||
554 | if ssl_options is None: |
|
537 | if ssl_options is None: | |
555 | self.log.critical(warning + " and not using encryption. This " |
|
538 | self.log.critical(warning + " and not using encryption. This " | |
556 | "is not recommended.") |
|
539 | "is not recommended.") | |
557 |
if not self.password |
|
540 | if not self.password: | |
558 | self.log.critical(warning + " and not using authentication. " |
|
541 | self.log.critical(warning + " and not using authentication. " | |
559 | "This is highly insecure and not recommended.") |
|
542 | "This is highly insecure and not recommended.") | |
560 | success = None |
|
543 | success = None |
@@ -22,7 +22,7 b' from zmq.utils import jsonapi' | |||||
22 |
|
22 | |||
23 | from IPython.utils.jsonutil import date_default |
|
23 | from IPython.utils.jsonutil import date_default | |
24 |
|
24 | |||
25 |
from ...base.handlers import IPythonHandler |
|
25 | from ...base.handlers import IPythonHandler | |
26 |
|
26 | |||
27 | #----------------------------------------------------------------------------- |
|
27 | #----------------------------------------------------------------------------- | |
28 | # Notebook web service handlers |
|
28 | # Notebook web service handlers | |
@@ -30,7 +30,7 b' from ...base.handlers import IPythonHandler, authenticate_unless_readonly' | |||||
30 |
|
30 | |||
31 | class NotebookRootHandler(IPythonHandler): |
|
31 | class NotebookRootHandler(IPythonHandler): | |
32 |
|
32 | |||
33 |
@authenticate |
|
33 | @web.authenticated | |
34 | def get(self): |
|
34 | def get(self): | |
35 | nbm = self.notebook_manager |
|
35 | nbm = self.notebook_manager | |
36 | km = self.kernel_manager |
|
36 | km = self.kernel_manager | |
@@ -57,7 +57,7 b' class NotebookHandler(IPythonHandler):' | |||||
57 |
|
57 | |||
58 | SUPPORTED_METHODS = ('GET', 'PUT', 'DELETE') |
|
58 | SUPPORTED_METHODS = ('GET', 'PUT', 'DELETE') | |
59 |
|
59 | |||
60 |
@authenticate |
|
60 | @web.authenticated | |
61 | def get(self, notebook_id): |
|
61 | def get(self, notebook_id): | |
62 | nbm = self.notebook_manager |
|
62 | nbm = self.notebook_manager | |
63 | format = self.get_argument('format', default='json') |
|
63 | format = self.get_argument('format', default='json') |
@@ -148,10 +148,6 b' var IPython = (function (IPython) {' | |||||
148 | */ |
|
148 | */ | |
149 | CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) { |
|
149 | CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) { | |
150 |
|
150 | |||
151 | if (this.read_only){ |
|
|||
152 | return false; |
|
|||
153 | } |
|
|||
154 |
|
||||
155 | var that = this; |
|
151 | var that = this; | |
156 | // whatever key is pressed, first, cancel the tooltip request before |
|
152 | // whatever key is pressed, first, cancel the tooltip request before | |
157 | // they are sent, and remove tooltip if any, except for tab again |
|
153 | // they are sent, and remove tooltip if any, except for tab again |
@@ -43,7 +43,6 b' function (marked) {' | |||||
43 |
|
43 | |||
44 | IPython.mathjaxutils.init(); |
|
44 | IPython.mathjaxutils.init(); | |
45 |
|
45 | |||
46 | IPython.read_only = $('body').data('readOnly') === 'True'; |
|
|||
47 | $('#ipython-main-app').addClass('border-box-sizing'); |
|
46 | $('#ipython-main-app').addClass('border-box-sizing'); | |
48 | $('div#notebook_panel').addClass('border-box-sizing'); |
|
47 | $('div#notebook_panel').addClass('border-box-sizing'); | |
49 |
|
48 | |||
@@ -54,7 +53,7 b' function (marked) {' | |||||
54 | IPython.pager = new IPython.Pager('div#pager', 'div#pager_splitter'); |
|
53 | IPython.pager = new IPython.Pager('div#pager', 'div#pager_splitter'); | |
55 | IPython.quick_help = new IPython.QuickHelp(); |
|
54 | IPython.quick_help = new IPython.QuickHelp(); | |
56 | IPython.login_widget = new IPython.LoginWidget('span#login_widget',{baseProjectUrl:baseProjectUrl}); |
|
55 | IPython.login_widget = new IPython.LoginWidget('span#login_widget',{baseProjectUrl:baseProjectUrl}); | |
57 |
IPython.notebook = new IPython.Notebook('div#notebook',{baseProjectUrl:baseProjectUrl |
|
56 | IPython.notebook = new IPython.Notebook('div#notebook',{baseProjectUrl:baseProjectUrl}); | |
58 | IPython.save_widget = new IPython.SaveWidget('span#save_widget'); |
|
57 | IPython.save_widget = new IPython.SaveWidget('span#save_widget'); | |
59 | IPython.menubar = new IPython.MenuBar('#menubar',{baseProjectUrl:baseProjectUrl}) |
|
58 | IPython.menubar = new IPython.MenuBar('#menubar',{baseProjectUrl:baseProjectUrl}) | |
60 | IPython.toolbar = new IPython.MainToolBar('#maintoolbar-container') |
|
59 | IPython.toolbar = new IPython.MainToolBar('#maintoolbar-container') | |
@@ -75,15 +74,6 b' function (marked) {' | |||||
75 | } |
|
74 | } | |
76 | $('#fonttest').remove(); |
|
75 | $('#fonttest').remove(); | |
77 |
|
76 | |||
78 | if(IPython.read_only){ |
|
|||
79 | // hide various elements from read-only view |
|
|||
80 | $('div#pager').remove(); |
|
|||
81 | $('div#pager_splitter').remove(); |
|
|||
82 |
|
||||
83 | // set the notebook name field as not modifiable |
|
|||
84 | $('#notebook_name').attr('disabled','disabled') |
|
|||
85 | } |
|
|||
86 |
|
||||
87 | IPython.page.show(); |
|
77 | IPython.page.show(); | |
88 |
|
78 | |||
89 | IPython.layout_manager.do_resize(); |
|
79 | IPython.layout_manager.do_resize(); |
@@ -25,7 +25,6 b' var IPython = (function (IPython) {' | |||||
25 | var Notebook = function (selector, options) { |
|
25 | var Notebook = function (selector, options) { | |
26 | var options = options || {}; |
|
26 | var options = options || {}; | |
27 | this._baseProjectUrl = options.baseProjectUrl; |
|
27 | this._baseProjectUrl = options.baseProjectUrl; | |
28 | this.read_only = options.read_only || IPython.read_only; |
|
|||
29 |
|
28 | |||
30 | this.element = $(selector); |
|
29 | this.element = $(selector); | |
31 | this.element.scroll(); |
|
30 | this.element.scroll(); | |
@@ -91,7 +90,6 b' var IPython = (function (IPython) {' | |||||
91 | this.container = $("<div/>").addClass("container").attr("id", "notebook-container"); |
|
90 | this.container = $("<div/>").addClass("container").attr("id", "notebook-container"); | |
92 | var end_space = $('<div/>').addClass('end_space'); |
|
91 | var end_space = $('<div/>').addClass('end_space'); | |
93 | end_space.dblclick(function (e) { |
|
92 | end_space.dblclick(function (e) { | |
94 | if (that.read_only) return; |
|
|||
95 | var ncells = that.ncells(); |
|
93 | var ncells = that.ncells(); | |
96 | that.insert_cell_below('code',ncells-1); |
|
94 | that.insert_cell_below('code',ncells-1); | |
97 | }); |
|
95 | }); | |
@@ -138,8 +136,6 b' var IPython = (function (IPython) {' | |||||
138 |
|
136 | |||
139 |
|
137 | |||
140 | $(document).keydown(function (event) { |
|
138 | $(document).keydown(function (event) { | |
141 | // console.log(event); |
|
|||
142 | if (that.read_only) return true; |
|
|||
143 |
|
139 | |||
144 | // Save (CTRL+S) or (AppleKey+S) |
|
140 | // Save (CTRL+S) or (AppleKey+S) | |
145 | //metaKey = applekey on mac |
|
141 | //metaKey = applekey on mac | |
@@ -366,7 +362,7 b' var IPython = (function (IPython) {' | |||||
366 | } |
|
362 | } | |
367 | // if we are autosaving, trigger an autosave on nav-away. |
|
363 | // if we are autosaving, trigger an autosave on nav-away. | |
368 | // still warn, because if we don't the autosave may fail. |
|
364 | // still warn, because if we don't the autosave may fail. | |
369 |
if (that.dirty |
|
365 | if (that.dirty) { | |
370 | if ( that.autosave_interval ) { |
|
366 | if ( that.autosave_interval ) { | |
371 | // schedule autosave in a timeout |
|
367 | // schedule autosave in a timeout | |
372 | // this gives you a chance to forcefully discard changes |
|
368 | // this gives you a chance to forcefully discard changes | |
@@ -1785,11 +1781,10 b' var IPython = (function (IPython) {' | |||||
1785 |
|
1781 | |||
1786 | // Create the kernel after the notebook is completely loaded to prevent |
|
1782 | // Create the kernel after the notebook is completely loaded to prevent | |
1787 | // code execution upon loading, which is a security risk. |
|
1783 | // code execution upon loading, which is a security risk. | |
1788 |
|
|
1784 | this.start_kernel(); | |
1789 | this.start_kernel(); |
|
1785 | // load our checkpoint list | |
1790 | // load our checkpoint list |
|
1786 | IPython.notebook.list_checkpoints(); | |
1791 | IPython.notebook.list_checkpoints(); |
|
1787 | ||
1792 | } |
|
|||
1793 | $([IPython.events]).trigger('notebook_loaded.Notebook'); |
|
1788 | $([IPython.events]).trigger('notebook_loaded.Notebook'); | |
1794 | }; |
|
1789 | }; | |
1795 |
|
1790 |
@@ -157,7 +157,6 b' var IPython = (function (IPython) {' | |||||
157 | * @method edit |
|
157 | * @method edit | |
158 | */ |
|
158 | */ | |
159 | TextCell.prototype.edit = function () { |
|
159 | TextCell.prototype.edit = function () { | |
160 | if ( this.read_only ) return; |
|
|||
161 | if (this.rendered === true) { |
|
160 | if (this.rendered === true) { | |
162 | var text_cell = this.element; |
|
161 | var text_cell = this.element; | |
163 | var output = text_cell.find("div.text_cell_render"); |
|
162 | var output = text_cell.find("div.text_cell_render"); |
@@ -17,7 +17,6 b' $(document).ready(function () {' | |||||
17 | window.open($('body').data('baseProjectUrl')+'new'); |
|
17 | window.open($('body').data('baseProjectUrl')+'new'); | |
18 | }); |
|
18 | }); | |
19 |
|
19 | |||
20 | IPython.read_only = $('body').data('readOnly') === 'True'; |
|
|||
21 | IPython.notebook_list = new IPython.NotebookList('#notebook_list'); |
|
20 | IPython.notebook_list = new IPython.NotebookList('#notebook_list'); | |
22 | IPython.cluster_list = new IPython.ClusterList('#cluster_list'); |
|
21 | IPython.cluster_list = new IPython.ClusterList('#cluster_list'); | |
23 | IPython.login_widget = new IPython.LoginWidget('#login_widget'); |
|
22 | IPython.login_widget = new IPython.LoginWidget('#login_widget'); |
@@ -34,9 +34,6 b' var IPython = (function (IPython) {' | |||||
34 |
|
34 | |||
35 |
|
35 | |||
36 | NotebookList.prototype.bind_events = function () { |
|
36 | NotebookList.prototype.bind_events = function () { | |
37 | if (IPython.read_only){ |
|
|||
38 | return; |
|
|||
39 | } |
|
|||
40 | var that = this; |
|
37 | var that = this; | |
41 | $('#refresh_notebook_list').click(function () { |
|
38 | $('#refresh_notebook_list').click(function () { | |
42 | that.load_list(); |
|
39 | that.load_list(); | |
@@ -129,13 +126,11 b' var IPython = (function (IPython) {' | |||||
129 | var kernel = data[i].kernel_id; |
|
126 | var kernel = data[i].kernel_id; | |
130 | var item = this.new_notebook_item(i); |
|
127 | var item = this.new_notebook_item(i); | |
131 | this.add_link(notebook_id, nbname, item); |
|
128 | this.add_link(notebook_id, nbname, item); | |
132 | if (!IPython.read_only){ |
|
129 | // hide delete buttons when readonly | |
133 | // hide delete buttons when readonly |
|
130 | if(kernel == null){ | |
134 | if(kernel == null){ |
|
131 | this.add_delete_button(item); | |
135 | this.add_delete_button(item); |
|
132 | } else { | |
136 | } else { |
|
133 | this.add_shutdown_button(item,kernel); | |
137 | this.add_shutdown_button(item,kernel); |
|
|||
138 | } |
|
|||
139 | } |
|
134 | } | |
140 | }; |
|
135 | }; | |
141 | }; |
|
136 | }; |
@@ -20,7 +20,7 b'' | |||||
20 | {% endfor %} |
|
20 | {% endfor %} | |
21 | {% endif %} |
|
21 | {% endif %} | |
22 |
|
22 | |||
23 |
{% if |
|
23 | {% if not login_available %} | |
24 | Proceed to the <a href="{{base_project_url}}">dashboard</a>. |
|
24 | Proceed to the <a href="{{base_project_url}}">dashboard</a>. | |
25 | {% else %} |
|
25 | {% else %} | |
26 | Proceed to the <a href="{{base_project_url}}login">login page</a>. |
|
26 | Proceed to the <a href="{{base_project_url}}login">login page</a>. |
@@ -24,7 +24,6 b' window.mathjax_url = "{{mathjax_url}}";' | |||||
24 | data-project={{project}} |
|
24 | data-project={{project}} | |
25 | data-base-project-url={{base_project_url}} |
|
25 | data-base-project-url={{base_project_url}} | |
26 | data-base-kernel-url={{base_kernel_url}} |
|
26 | data-base-kernel-url={{base_kernel_url}} | |
27 | data-read-only={{read_only and not logged_in}} |
|
|||
28 | data-notebook-id={{notebook_id}} |
|
27 | data-notebook-id={{notebook_id}} | |
29 | class="notebook_app" |
|
28 | class="notebook_app" | |
30 |
|
29 |
@@ -13,7 +13,6 b'' | |||||
13 | data-project={{project}} |
|
13 | data-project={{project}} | |
14 | data-base-project-url={{base_project_url}} |
|
14 | data-base-project-url={{base_project_url}} | |
15 | data-base-kernel-url={{base_kernel_url}} |
|
15 | data-base-kernel-url={{base_kernel_url}} | |
16 | data-read-only={{read_only}} |
|
|||
17 |
|
16 | |||
18 | {% endblock %} |
|
17 | {% endblock %} | |
19 |
|
18 | |||
@@ -30,7 +29,7 b' data-read-only={{read_only}}' | |||||
30 |
|
29 | |||
31 | <div class="tab-content"> |
|
30 | <div class="tab-content"> | |
32 | <div id="notebooks" class="tab-pane active"> |
|
31 | <div id="notebooks" class="tab-pane active"> | |
33 |
{% if logged_in |
|
32 | {% if logged_in %} | |
34 | <div id="notebook_toolbar"> |
|
33 | <div id="notebook_toolbar"> | |
35 | <form id='alternate_upload' class='alternate_upload' > |
|
34 | <form id='alternate_upload' class='alternate_upload' > | |
36 | <span id="drag_info" style="position:absolute" > |
|
35 | <span id="drag_info" style="position:absolute" > |
@@ -16,7 +16,8 b' Authors:' | |||||
16 | # Imports |
|
16 | # Imports | |
17 | #----------------------------------------------------------------------------- |
|
17 | #----------------------------------------------------------------------------- | |
18 |
|
18 | |||
19 | from ..base.handlers import IPythonHandler, authenticate_unless_readonly |
|
19 | from tornado import web | |
|
20 | from ..base.handlers import IPythonHandler | |||
20 |
|
21 | |||
21 | #----------------------------------------------------------------------------- |
|
22 | #----------------------------------------------------------------------------- | |
22 | # Handlers |
|
23 | # Handlers | |
@@ -25,7 +26,7 b' from ..base.handlers import IPythonHandler, authenticate_unless_readonly' | |||||
25 |
|
26 | |||
26 | class ProjectDashboardHandler(IPythonHandler): |
|
27 | class ProjectDashboardHandler(IPythonHandler): | |
27 |
|
28 | |||
28 |
@authenticate |
|
29 | @web.authenticated | |
29 | def get(self): |
|
30 | def get(self): | |
30 | self.write(self.render_template('tree.html', |
|
31 | self.write(self.render_template('tree.html', | |
31 | project=self.project, |
|
32 | project=self.project, |
General Comments 0
You need to be logged in to leave comments.
Login now