Commit c36cfb56558fd781bfeb0a4a834f9fd9b860cffb

Authored by Miguel Barão
1 parent 43785de6
Exists in master and in 1 other branch dev

- added try/catch to check if certificates are present.

- fixed 3 bugs in serve.py.
- show total topics and questions loaded in logs.
@@ -287,6 +287,7 @@ def build_dependency_graph(config={}): @@ -287,6 +287,7 @@ def build_dependency_graph(config={}):
287 287
288 # iterate over topics and build graph 288 # iterate over topics and build graph
289 topics = config.get('topics', {}) 289 topics = config.get('topics', {})
  290 + tcount = qcount = 0 # topic and question counters
290 for ref,attr in topics.items(): 291 for ref,attr in topics.items():
291 g.add_node(ref) 292 g.add_node(ref)
292 tnode = g.node[ref] # current node (topic) 293 tnode = g.node[ref] # current node (topic)
@@ -313,5 +314,8 @@ def build_dependency_graph(config={}): @@ -313,5 +314,8 @@ def build_dependency_graph(config={}):
313 tnode['factory'][q['ref']] = QFactory(q) 314 tnode['factory'][q['ref']] = QFactory(q)
314 315
315 logger.info(f'{len(tnode["questions"]):6} {ref}') 316 logger.info(f'{len(tnode["questions"]):6} {ref}')
  317 + qcount += len(tnode["questions"]) # count total questions
  318 + tcount += 1
316 319
  320 + logger.info(f'Total loaded: {tcount} topics, {qcount} questions')
317 return g 321 return g
@@ -13,7 +13,7 @@ from concurrent.futures import ThreadPoolExecutor @@ -13,7 +13,7 @@ from concurrent.futures import ThreadPoolExecutor
13 import tornado.ioloop 13 import tornado.ioloop
14 import tornado.web 14 import tornado.web
15 import tornado.httpserver 15 import tornado.httpserver
16 -from tornado import template #, gen 16 +from tornado import template, iostream, gen
17 17
18 from tornado.concurrent import run_on_executor 18 from tornado.concurrent import run_on_executor
19 from tornado.platform.asyncio import to_tornado_future 19 from tornado.platform.asyncio import to_tornado_future
@@ -101,7 +101,7 @@ class ChangePasswordHandler(BaseHandler): @@ -101,7 +101,7 @@ class ChangePasswordHandler(BaseHandler):
101 @tornado.web.authenticated 101 @tornado.web.authenticated
102 def post(self): 102 def post(self):
103 uid = self.current_user 103 uid = self.current_user
104 - pw = self.get_body_arguments('new_password')[0]; 104 + pw = self.get_body_arguments('new_password')[0]
105 105
106 if self.learn.change_password(uid, pw): 106 if self.learn.change_password(uid, pw):
107 notification = tornado.escape.to_unicode(self.render_string('notification.html', type='success', msg='A password foi alterada!')) 107 notification = tornado.escape.to_unicode(self.render_string('notification.html', type='success', msg='A password foi alterada!'))
@@ -152,12 +152,13 @@ class TopicHandler(BaseHandler): @@ -152,12 +152,13 @@ class TopicHandler(BaseHandler):
152 # Based on https://bhch.github.io/posts/2017/12/serving-large-files-with-tornado-safely-without-blocking/ 152 # Based on https://bhch.github.io/posts/2017/12/serving-large-files-with-tornado-safely-without-blocking/
153 # ---------------------------------------------------------------------------- 153 # ----------------------------------------------------------------------------
154 class FileHandler(BaseHandler): 154 class FileHandler(BaseHandler):
  155 + chunk_size = 4 * 1024 * 1024 # serve up to 4 MiB multiple times
  156 +
155 @tornado.web.authenticated 157 @tornado.web.authenticated
156 async def get(self, filename): 158 async def get(self, filename):
157 uid = self.current_user 159 uid = self.current_user
158 public_dir = self.learn.get_current_public_dir(uid) 160 public_dir = self.learn.get_current_public_dir(uid)
159 filepath = path.expanduser(path.join(public_dir, filename)) 161 filepath = path.expanduser(path.join(public_dir, filename))
160 - chunk_size = 1024 * 1024 # serve up to 1MiB multiple times  
161 try: 162 try:
162 f = open(filepath, 'rb') 163 f = open(filepath, 'rb')
163 except FileNotFoundError: 164 except FileNotFoundError:
@@ -166,7 +167,7 @@ class FileHandler(BaseHandler): @@ -166,7 +167,7 @@ class FileHandler(BaseHandler):
166 logging.error(f'No permission: {filepath}') 167 logging.error(f'No permission: {filepath}')
167 else: 168 else:
168 with f: 169 with f:
169 - chunk = f.read(chunk_size) 170 + chunk = f.read(self.chunk_size)
170 while chunk: 171 while chunk:
171 try: 172 try:
172 self.write(chunk) # write the cunk to response 173 self.write(chunk) # write the cunk to response
@@ -178,7 +179,7 @@ class FileHandler(BaseHandler): @@ -178,7 +179,7 @@ class FileHandler(BaseHandler):
178 del chunk 179 del chunk
179 await gen.sleep(0.000000001) # 1 nanosecond (hack) 180 await gen.sleep(0.000000001) # 1 nanosecond (hack)
180 # in tornnado 5.0 use `await asyncio.sleep(0)` instead 181 # in tornnado 5.0 use `await asyncio.sleep(0)` instead
181 - chunk = f.read(chunk_size) 182 + chunk = f.read(self.chunk_size)
182 183
183 184
184 # ---------------------------------------------------------------------------- 185 # ----------------------------------------------------------------------------
@@ -320,12 +321,17 @@ def main(): @@ -320,12 +321,17 @@ def main():
320 raise e 321 raise e
321 322
322 # --- create webserver 323 # --- create webserver
323 - http_server = tornado.httpserver.HTTPServer(webapp,  
324 - ssl_options={  
325 - "certfile": "certs/cert.pem",  
326 - "keyfile": "certs/privkey.pem"  
327 - })  
328 - http_server.listen(8443) 324 + try:
  325 + http_server = tornado.httpserver.HTTPServer(webapp,
  326 + ssl_options={
  327 + "certfile": "certs/cert.pem",
  328 + "keyfile": "certs/privkey.pem"
  329 + })
  330 + except ValueError:
  331 + logging.critical('Certificates cert.pem, privkey.pem not found')
  332 + sys.exit(1)
  333 + else:
  334 + http_server.listen(8443)
329 335
330 # --- run webserver 336 # --- run webserver
331 logging.info('Webserver running...') 337 logging.info('Webserver running...')
templates/maintopics.html
@@ -98,9 +98,11 @@ @@ -98,9 +98,11 @@
98 </a> 98 </a>
99 {% end %} 99 {% end %}
100 {% end %} 100 {% end %}
101 - </div> <!-- list-group --> 101 + </div>
  102 + <!-- list-group -->
102 </div> 103 </div>
103 104
  105 +
104 <!-- === Change Password Modal =========================================== --> 106 <!-- === Change Password Modal =========================================== -->
105 <div id="password_modal" class="modal fade" tabindex="-1" role="dialog"> 107 <div id="password_modal" class="modal fade" tabindex="-1" role="dialog">
106 <div class="modal-dialog modal-sm" role="document"> 108 <div class="modal-dialog modal-sm" role="document">