Commit 0824b00

bryfry <bryon.fryer@gmail.com>
2013-12-16 22:45:21
begin auth
1 parent 14d7aed
static/ffu.css
@@ -1,6 +1,20 @@
 body {
   padding-top: 60px;
 }
-#upload_text {
+#form-upload {
+  padding: 15px;
+}
+#upload-zone {
+  margin-bottom: 0px;
+}
+#upload-text {
   margin-bottom: 0px;
+  height: 55px;
+  line-height: 55px;
+}
+.top-padding { 
+  margin-top:20px; 
+}
+.bot-padding { 
+  margin-bottom:20px; 
 }
static/ffu.js
@@ -0,0 +1,76 @@
+if (window.File && window.FileList) {
+  var form = $("#form-upload");
+  form.upload_zone = $("#upload-zone");
+  form.input_file = $("#fileselect"); 
+  form.file_list = $("#filelist"); 
+  form.upload_zone.files = new Array();
+  form.submit (function (e) {
+    e.preventDefault();
+    
+    // generate formdata to upload
+    var file_data = new FormData(form);
+    for (var i=0, file; file=form.upload_zone.files[i]; i++){
+      file_data.append("fileselect" + i.toString(), file);
+    }
+    
+    // send formdata to server
+    var request = new XMLHttpRequest();
+    request.open ($(this).attr("method"), $(this).attr("action"), true);
+    request.onload = function(oEvent) {
+      if (request.status == 200) {
+        form.upload_zone.innerHTML = "Uploaded!";
+      } else {
+        form.upload_zone.innerHTML = "Error " + request.status + " occurred uploading your file.<br \/>";
+      }
+    };       
+    form.file_list.empty();
+    console.log("emptied");
+    request.send(file_data);
+  }); 
+
+  // manage meta-file array
+  var handleFiles = function (files) {
+    for (var i=0, file; file=files[i]; i++){
+      form.upload_zone.files.push (file);
+      form.file_list.append ("<li class='list-group-item'>"+file.name+"\t"+file.size+"B "+"</li>");
+    }
+  } // end handleFiles
+
+  // watch for changes in form-input-file element
+  form.input_file.change (function (event) { 
+    handleFiles (form.input_file[0].files); // jquery get to FileList at [0]
+  });
+  
+  // open input-file-multiple dialogue
+  form.upload_zone.click (function (event) {
+    form.input_file.focus();
+    form.input_file.click();
+  });
+
+} // end upload jquery functions
+
+$(document).on ('dragstart dragenter dragover', function (e) {
+  if ($.inArray('Files', e.originalEvent.dataTransfer.types) > -1) {
+    e.stopPropagation();
+    e.preventDefault();
+    $('#upload-zone').css('border', '2px dashed #0B85A1');
+  }
+});
+
+$(document).on ('dragleave dragged', function (e) {
+    e.stopPropagation();
+    e.preventDefault();
+    $('#upload-zone').css('border', '');
+});
+
+ $(document).on ('drop', function (e) {
+    e.stopPropagation();
+    e.preventDefault();
+    $('#upload-zone').css('border', '');
+    if (e.target.id =='upload-zone' || $(e.target).parent().is('#upload-zone')){
+      handleFiles(e.originalEvent.dataTransfer.files);
+    }
+});
+
+
+
static/signin.css
@@ -0,0 +1,39 @@
+body {
+  padding-top: 60px;
+  padding-bottom: 40px;
+}
+
+.form-signin {
+  max-width: 330px;
+  padding: 15px;
+  margin: 0 auto;
+}
+.form-signin .form-signin-heading,
+.form-signin .checkbox {
+  margin-bottom: 10px;
+}
+.form-signin .checkbox {
+  font-weight: normal;
+}
+.form-signin .form-control {
+  position: relative;
+  font-size: 16px;
+  height: auto;
+  padding: 10px;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+.form-signin .form-control:focus {
+  z-index: 2;
+}
+.form-signin input[type="text"] {
+  margin-bottom: -1px;
+  border-bottom-left-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.form-signin input[type="password"] {
+  margin-bottom: 10px;
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
ffu.py
@@ -3,14 +3,50 @@ import tornado.web
 import logging
 import tarfile
 import uuid
+import base64
 from StringIO import StringIO
 import os
 
+class BaseHandler(tornado.web.RequestHandler):
+  def get_login_url(self):
+    return u"/login"
+  def get_current_user(self):
+    user_json = self.get_secure_cookie("user")
+    if user_json:
+      return tornado.escape.json_decode(user_json)
+    else:
+      return None
+
+class LoginHandler(BaseHandler):
+  def get(self):
+    self.render('login.html', next=self.get_argument("next","/"))
+  def post(self):
+    print self
+    print vars(self)
+    username = self.get_argument("username", "")
+    password = self.get_argument("password", "")
+    print "login: ",username," ",password 
+    auth = False
+    if username == "user" and password == "pass":
+      auth = True
+    if auth:
+      self.set_current_user(username)
+      self.redirect(self.get_argument("next","/"))
+    else:
+      error_msg = u"?error=" + tornado.escape.url_escape("Login Failed")
+      self.redirect(u"/login" + error_msg)
+  def set_current_user(self, user):
+    if user:
+      self.set_secure_cookie("user", tornado.escape.json_encode(user))
+    else:
+      self.clear_cookie("user")
+
+class LogoutHandler(BaseHandler):
+  def get(self):
+    self.clear_cookie("user")
+    self.redirect(u"/login")
+
 class UploadHandler(tornado.web.RequestHandler):
-  
-#  def _handle_request_exception(self, e):
-#    logging.error('error',e)
-  
   def get(self):
     self.render("index.html")
   
@@ -27,15 +63,19 @@ class UploadHandler(tornado.web.RequestHandler):
         f_info.size = len(f[0]['body'])
         tar.addfile(f_info, StringIO(f[0]['body']))
       tar.close()
-    #self.render("index.html")
 
-  settings = {
-    "static_path": os.path.join(os.path.dirname(__file__),"static"),
+handlers = [
+  (r"/", UploadHandler),
+  (r"/login", LoginHandler),
+  (r"/logout", LogoutHandler),
+]  
+
+settings = {
+  "static_path": os.path.join(os.path.dirname(__file__),"static"),
+  "cookie_secret": base64.b64encode(uuid.uuid4().bytes + uuid.uuid4().bytes),
 }
 
-application = tornado.web.Application([
-  (r"/", UploadHandler),
-  ], debug=True, static_path=os.path.join(os.path.dirname(__file__),'static'))
+application = tornado.web.Application(handlers, **settings )
 
 if __name__ == "__main__":
   application.listen(8888)
index.html
@@ -32,97 +32,28 @@
   </div>
 
   <div class="container">
-    <form id="upload" enctype="multipart/form-data" action="" method="post">
+    <form id="form-upload" enctype="multipart/form-data" action="" method="post">
       <input type="file" id="fileselect" name="fileselect" multiple="multiple" style="display:none"/>
-      <div id="upload_zone" class="well upload_zone">
-        <p id="upload_text" class="lead text-center text-muted">Drop files or Click here</p>
+      <div class="row">
+        <div class="col-md-8 col-sm-8 bot-padding">
+          <div id="upload-zone" class="well upload-zone">
+            <p id="upload-text" class="lead text-center text-muted">Drop files or Click here</p>
+          </div>
+        </div>
+        <div class="col-md-4 col-sm-4 bot-padding">
+          <button class="btn btn-lg btn-default btn-block" type="submit">Upload</button>
+          <button class="btn btn-lg btn-default btn-block" type="reset">Clear</button>
+        </div>
       </div>
+      <div class="row">
+      <div class="col-xs-12">
       <ul id="filelist" class="list-group"></ul>
-      <button type="submit">Upload</button>
+      </div>
+      </div>
     </form>
   </div><!-- /.container -->
+
   <script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
   <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
-  <script>
-    if (window.File && window.FileList) {
-      var form = $("#upload");
-      form.upload_zone = $("#upload_zone");
-      form.input_file = $("#fileselect"); 
-      form.file_list = $("#filelist"); 
-      form.upload_zone.files = new Array();
-      form.submit (function (e) {
-        e.preventDefault();
-        
-        // generate formdata to upload
-        var file_data = new FormData(form);
-        for (var i=0, file; file=form.upload_zone.files[i]; i++){
-          file_data.append("fileselect" + i.toString(), file);
-        }
-        
-        // send formdata to server
-        var request = new XMLHttpRequest();
-        request.open ($(this).attr("method"), $(this).attr("action"), true);
-        request.onload = function(oEvent) {
-          if (request.status == 200) {
-            form.upload_zone.innerHTML = "Uploaded!";
-          } else {
-            form.upload_zone.innerHTML = "Error " + request.status + " occurred uploading your file.<br \/>";
-          }
-        };       
-        request.send(file_data);
-      }); 
-
-      // manage meta-file array
-      var handleFiles = function (files) {
-        for (var i=0, file; file=files[i]; i++){
-          form.upload_zone.files.push (file);
-          form.file_list.append ("<li class='list-group-item'>"+file.name+"</li>");
-        }
-      } // end handleFiles
-
-      // watch for changes in form-input-file element
-      form.input_file.change (function (event) { 
-        handleFiles (form.input_file[0].files); // jquery get to FileList at [0]
-      });
-      
-      // open input-file-multiple dialogue
-      form.upload_zone.click (function (event) {
-        form.input_file.focus();
-        form.input_file.click();
-      });
-
-      // TODO add clear button
-      // TODO move upload up with upload_zone
-      // TODO add X button area on list elements to remove each
-      // TODO (python) send success message 
-      // TODO file name collisions deduplication
-    
-    } // end upload jquery functions
-    
-    $(document).on ('dragstart dragenter dragover', function (e) {
-      if ($.inArray('Files', e.originalEvent.dataTransfer.types) > -1) {
-        e.stopPropagation();
-        e.preventDefault();
-        $('#upload_zone').css('border', '2px dashed #0B85A1');
-      }
-    });
-    
-    $(document).on ('dragleave dragged', function (e) {
-        e.stopPropagation();
-        e.preventDefault();
-        $('#upload_zone').css('border', '');
-    });
-
-     $(document).on ('drop', function (e) {
-        e.stopPropagation();
-        e.preventDefault();
-        $('#upload_zone').css('border', '');
-        if (e.target.id =='upload_zone' || $(e.target).parent().is('#upload_zone')){
-          handleFiles(e.originalEvent.dataTransfer.files);
-        }
-    });
-
-
-
-  </script>
+  <script src="{{ static_url("ffu.js") }}"></script>
 </body>
login.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta name="description" content="">
+  <meta name="author" content="">
+  <link rel="shortcut icon" href="{{ static_url("images/favicon.ico")}}">
+  <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
+  <link rel="stylesheet" href="{{ static_url("signin.css") }}">
+</head>
+
+<body>
+  <div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
+    <div class="container">
+      <div class="navbar-header">
+        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
+          <span class="sr-only">Toggle navigation</span>
+          <span class="icon-bar"></span>
+          <span class="icon-bar"></span>
+          <span class="icon-bar"></span>
+        </button>
+        <a class="navbar-brand" href="#">FFU</a>
+      </div>
+      <div class="collapse navbar-collapse">
+        <ul class="nav navbar-nav">
+          <li class="active"><a href="#">Home</a></li>
+          <li><a href="#about">Admin</a></li>
+        </ul>
+      </div><!--/.nav-collapse -->
+    </div>
+  </div>
+
+  <div class="container">
+    <form class="form-signin" role="form" action="" method="post">
+      <input type="text" class="form-control" name="username" placeholder="Username" required autofocus>
+      <input type="password" class="form-control" name="password" placeholder="Password" required>
+      <!--<label class="checkbox">
+        <input type="checkbox" value="remember-me"> Remember me
+      </label>-->
+      <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
+    </form>
+  </div> <!-- /container -->
+  <script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
+  <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
+  <script src="{{ static_url("ffu.js") }}"></script>
+</body>
README.md
@@ -0,0 +1,8 @@
+TODO Auth
+TODO add clear button
+TODO move upload up with upload_zone
+TODO add X button area on list elements to remove each
+TODO (python) send success message 
+TODO file name collisions deduplication
+TODO Disable Updload / Clear when appropriate
+