Permalink
Browse files

Merged uplusmessaging into subdirectory

  • Loading branch information...
1 parent ec85127 commit cdc4a911ce3a7b4bef1c53f6d7b69dee287a8111 Anthony committed Aug 31, 2012
@@ -0,0 +1 @@
+*.pyc
View
@@ -0,0 +1,4 @@
+uplusmessaging
+==============
+
+Collaborative Social Network Private Messaging
View
@@ -0,0 +1,13 @@
+application: uplusmessagingdemo
+version: 1
+runtime: python27
+api_version: 1
+threadsafe: true
+
+handlers:
+- url: /.*
+ script: main.app
+
+libraries:
+- name: jinja2
+ version: latest
@@ -0,0 +1,58 @@
+# Basic webapp2 handler with some useful methods
+#
+# render(template_name, template_vals={})
+# - template needs to be in template dir
+#
+#
+# WORKING WITH COOKIES
+#
+# set_cookie(name, value)
+# set_cookies({name1:value1, name2:value2})
+# get_cookie(name)
+# get_cookies([name1, name2...]) - return [value1, value2...]
+# get_cookies_dict([name1, name2...]) - return {name1:value1, name2:value2}
+#
+#
+# RETRIVING REQUEST PARAMS
+#
+# get_params([param1, param2...]) - return [value1, value2...]
+# get_params_dict([param1, param2...]) - return {param1:value1, param2:value2}
+
+import webapp2
+import jinja2
+import os
+
+
+head, tail = os.path.split(os.path.dirname(__file__))
+template_dir = os.path.join(head, "templates")
+
+jinja_environment=jinja2.Environment(
+ loader=jinja2.FileSystemLoader(template_dir), autoescape=True)
+
+class BaseHandler(webapp2.RequestHandler):
+ def render(self, template, vals={}):
+ template = jinja_environment.get_template("%s" % template)
+ self.response.out.write(template.render(vals))
+
+ def set_cookie(self, name, value):
+ name, value = str(name), str(value)
+ self.response.headers.add_header('Set-Cookie', '%s=%s' % (name, value))
+
+ def set_cookies(self, pairs):
+ for k, v in pairs.iteritems():
+ self.set_cookie(k, v)
+
+ def get_cookie(self, name):
+ return self.request.cookies.get(name)
+
+ def get_cookies(self, names):
+ return [self.get_cookie(name) for name in names]
+
+ def get_cookies_dict(self, names):
+ return {name:self.get_cookie(name) for name in names}
+
+ def get_params(self, params):
+ return [self.request.get(param) for param in params]
+
+ def get_params_dict(self, params):
+ return {param : self.request.get(param) for param in params}
No changes.
@@ -0,0 +1,45 @@
+# AUTHENTICATION
+#
+# @Authentication.do decorator check
+# if user is allowed to see a page
+#
+#
+# valid_login(username, password)
+# valid_log_token(username, log_token)
+# create_and_save_log_token(user)
+
+
+from models.User import User
+from externals.bcrypt import bcrypt as bc
+
+class Authentication(object):
+
+ @staticmethod
+ def do(fn):
+ def wrapper(self, *args):
+ username = self.request.cookies.get("username")
+ log_token = self.request.cookies.get("log_token")
+
+ if Authentication.valid_log_token(username, log_token):
+ return fn(self, *args)
+ else:
+ self.redirect("/forbidden")
+ return wrapper
+
+ @staticmethod
+ def valid_login(username, password):
+ user = User.get_user(username)
+ if user and bc.hashpw(password, user.password) == user.password:
+ return Authentication.create_and_save_log_token(user)
+
+ @staticmethod
+ def valid_log_token(username, log_token):
+ user = User.get_user(username)
+ return user and bc.hashpw(log_token, user.log_token) == user.log_token
+
+ @staticmethod
+ def create_and_save_log_token(user):
+ log_token = bc.gensalt()
+ user.log_token = bc.hashpw(log_token, bc.gensalt())
+ user.put()
+ return log_token
@@ -0,0 +1,5 @@
+from BaseHandler import *
+
+class Forbidden(BaseHandler):
+ def get(self):
+ self.render("forbidden_resource.html")
@@ -0,0 +1,10 @@
+from BaseHandler import *
+
+class HomePage(BaseHandler):
+ def get(self):
+ template_values = {'title' : self.get_title()}
+ self.render("index.html", template_values)
+
+ def get_title(self):
+ name = self.get_cookie('username')
+ return "Welcome Back, %s!" % name if name else "Welcome to UdacityPlus!"
@@ -0,0 +1,17 @@
+from BaseHandler import *
+from authentication import Authentication as aut
+from externals.bcrypt import bcrypt as bc
+
+class LoginPage(BaseHandler):
+ def get(self):
+ self.render("login.html")
+
+ def post(self):
+ params = self.get_params(["username", "password"])
+ log_token = aut.valid_login(*params)
+ if log_token:
+ username, _ = params
+ self.set_cookies({"username":username, "log_token":log_token})
+ self.redirect("/")
+ else:
+ self.redirect("/login")
@@ -0,0 +1,6 @@
+from BaseHandler import *
+
+class LogoutPage(BaseHandler):
+ def get(self):
+ self.set_cookies({"username":"", "log_token":""})
+ self.redirect("/")
@@ -0,0 +1,9 @@
+from BaseHandler import *
+from controllers.authentication import Authentication
+
+
+class MessagePage(BaseHandler):
+
+ @Authentication.do
+ def get(self):
+ self.response.out.write("Hello World")
@@ -0,0 +1,19 @@
+from BaseHandler import *
+from models.User import User
+from authentication import Authentication as aut
+
+class SignUpPage(BaseHandler):
+
+ def get(self):
+ self.render("signup.html")
+
+ def post(self):
+ params = self.get_params(["username", "email", "password"])
+ user = User.save(*params)
+
+ if user:
+ log_token = aut.create_and_save_log_token(user)
+ self.set_cookies({'username':user.username, 'log_token':log_token})
+ self.redirect("/")
+ else:
+ self.redirect("/signup")
No changes.
Submodule bcrypt added at 8fc098
View
@@ -0,0 +1,17 @@
+import webapp2
+from controllers.home import HomePage
+from controllers.signup import SignUpPage
+from controllers.login import LoginPage
+from controllers.logout import LogoutPage
+from controllers.forbidden import Forbidden
+from controllers.messages import MessagePage
+
+app = webapp2.WSGIApplication([
+ ('/', HomePage),
+ ('/signup', SignUpPage),
+ ('/login', LoginPage),
+ ('/logout', LogoutPage),
+ ('/forbidden', Forbidden),
+ ('/messages.*', MessagePage)
+ ], debug=True)
+
@@ -0,0 +1,71 @@
+# Simple user model that we can use
+# in further development of pm part
+#
+# Some helpful static methods added
+#
+#
+# VALIDATORS
+#
+# valid_password()
+# valid_username()
+# valid_email()
+# valid() - check all above
+#
+#
+# SAVE
+#
+# save() - save and return user if valid() else False
+#
+#
+# LOG TOKEN
+#
+# bcrypt.gensalt() is used for creating tokens
+# tokens in database are hashed with bcrypt
+# new token is generated with every new login
+
+
+from google.appengine.ext import db
+from externals.bcrypt import bcrypt as bc
+
+class User(db.Model):
+ username = db.StringProperty(required=True)
+ password = db.StringProperty(required=True)
+ email = db.StringProperty(required=True)
+ log_token = db.StringProperty(required=False)
+
+ @staticmethod
+ def get_user(username):
+ # shortcut for other classes that import User
+ return User.gql("WHERE username=:1", username).get()
+
+ @staticmethod
+ def valid_password(password):
+ return len(password) < 40
+
+ @staticmethod
+ def valid_username(username):
+ n = len(username)
+ users = User.get_user(username)
+ return not users and n > 4 and n < 21
+
+ @staticmethod
+ def valid_email(email):
+ emails = User.gql("WHERE email=:1", email).get()
+ #too lazy for regex now
+ return emails == None
+
+ @staticmethod
+ def valid(username, email, password):
+ return User.valid_password(password) and \
+ User.valid_username(username) and \
+ User.valid_email(email)
+
+ @staticmethod
+ def save(username, email, password):
+ if User.valid(username, email, password):
+ password = bc.hashpw(password, bc.gensalt())
+ # call to create and save log token is in signup controller
+ user = User(username = username, password = password, email = email)
+ user.put()
+ return user
+ return False
No changes.
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Messaging system demo</title>
+</head>
+<body>
+ <div id ="header">
+ <a href="/login">Login</a>
+ <a href="/signup">Sign up</a>
+ <a href="/logout">Logout</a>
+ <a href="/messages">Messages</a>
+ </div>
+ <div id="content">
+ {% block content %}
+ {% endblock %}
+ </div>
+</body>
+</html>
@@ -0,0 +1,5 @@
+{% extends "base.html" %}
+{% block content %}
+ <h1>You are not authorized to see this page</h1>
+ <p>Go to <a href="/login">Login</a> or <a href="/signup">Sign up</a></p>
+{% endblock %}
@@ -0,0 +1,4 @@
+{% extends "base.html" %}
+{% block content %}
+ <h1>{{ title }}</h1>
+{% endblock %}
@@ -0,0 +1,12 @@
+{% extends "base.html" %}
+{% block content %}
+ <form action="" method="Post">
+ <label for="username">Enter username:</label>
+ <input type="text" id="username" name="username">
+ <br />
+ <label for="password">Enter password:</label>
+ <input type="password" id="password" name="password">
+ <br />
+ <input type="submit">
+ </form>
+{% endblock %}
@@ -0,0 +1,15 @@
+{% extends "base.html" %}
+{% block content %}
+ <form action="" method="Post">
+ <label for="username">Username:</label>
+ <input type="text" id="username" name="username">
+ <br />
+ <label for="email">Email:</label>
+ <input type="text" id="email" name="email">
+ <br />
+ <label for="password">Password:</label>
+ <input type="password" id="password" name="password">
+ <br />
+ <input type="submit">
+ </form>
+{% endblock %}

0 comments on commit cdc4a91

Please sign in to comment.