Skip to content

Commit

Permalink
add login and auth in urls.py
Browse files Browse the repository at this point in the history
  • Loading branch information
zhichuanxiu committed Sep 19, 2015
1 parent ad77a6e commit 8a92f60
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 28 deletions.
9 changes: 5 additions & 4 deletions www/transwarp/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -1546,7 +1546,7 @@ def get_wsgi_application(self, debug=False):
def fn_route():
request_method = ctx.request.request_method
path_info = ctx.request.path_info
if request_method == 'GET':
if request_method=='GET':
fn = self._get_static.get(path_info, None)
if fn:
return fn()
Expand All @@ -1555,7 +1555,7 @@ def fn_route():
if args:
return fn(*args)
raise HttpError.notfound()
if request_method == 'POST':
if request_method=='POST':
fn = self._post_static.get(path_info, None)
if fn:
return fn()
Expand All @@ -1564,9 +1564,10 @@ def fn_route():
if args:
return fn(*args)
raise HttpError.notfound()
raise HttpError.badrequest()
raise badrequest()

fn_exec = _build_interceptor_chain(fn_route, *self._interceptors)
fn_exec = _build_interceptor_chain(fn_route, *self._interceptors)

def wsgi(env, start_response):
"""
Expand All @@ -1589,7 +1590,7 @@ def wsgi(env, start_response):
response.set_header('Location', e.location)
start_response(e.status, response.headers)
return []
except HttpError, e:
except _HttpError, e:
start_response(e.status, response.headers)
return ['<html><body><h1>', e.status, '</h1></body></html>']
except Exception, e:
Expand Down
127 changes: 125 additions & 2 deletions www/urls.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,139 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'Michael Liao'

import os, re, time, base64, hashlib, logging

from transwarp.web import get, post, ctx, view, interceptor, HttpError

from apis import api, APIError, APIValueError, APIPermissionError, APIResourceNotFoundError

from models import User, Blog, Comment
from config import configs

_COOKIE_NAME = 'awesession'
_COOKIE_KEY = configs.session.secret

def make_signed_cookie(id, password, max_age):
# build cookie string by: id-expires-md5
expires = str(int(time.time() + (max_age or 86400)))
L = [id, expires, hashlib.md5('%s-%s-%s-%s' % (id, password, expires, _COOKIE_KEY)).hexdigest()]
return '-'.join(L)

def parse_signed_cookie(cookie_str):
try:
L = cookie_str.split('-')
if len(L) != 3:
return None
id, expires, md5 = L
if int(expires) < time.time():
return None
user = User.get(id)
if user is None:
return None
if md5 != hashlib.md5('%s-%s-%s-%s' % (id, user.password, expires, _COOKIE_KEY)).hexdigest():
return None
return user
except:
return None

def check_admin():
user = ctx.request.user
if user and user.admin:
return
raise APIPermissionError('No permission.')

@interceptor('/')
def user_interceptor(next):
logging.info('try to bind user from session cookie...')
user = None
cookie = ctx.request.cookies.get(_COOKIE_NAME)
if cookie:
logging.info('parse session cookie...')
user = parse_signed_cookie(cookie)
if user:
logging.info('bind user <%s> to session...' % user.email)
ctx.request.user = user
return next()

@interceptor('/manage/')
def manage_interceptor(next):
user = ctx.request.user
if user and user.admin:
return next()
raise HttpError.seeother('/signin')

@view('blogs.html')
@get('/')
def index():
blogs = Blog.find_all()
user = User.find_first('where email=?', '[email protected]')
return dict(blogs=blogs, user=user)
return dict(blogs=blogs, user=ctx.request.user)

@view('signin.html')
@get('/signin')
def signin():
return dict()

@get('/signout')
def signout():
ctx.response.delete_cookie(_COOKIE_NAME)
raise HttpError.seeother('/')

@api
@post('/api/authenticate')
def authenticate():
i = ctx.request.input(remember='')
email = i.email.strip().lower()
password = i.password
remember = i.remember
user = User.find_first('where email=?', email)
if user is None:
raise APIError('auth:failed', 'email', 'Invalid email.')
elif user.password != password:
raise APIError('auth:failed', 'password', 'Invalid password.')
# make session cookie:
max_age = 604800 if remember=='true' else None
cookie = make_signed_cookie(user.id, user.password, max_age)
ctx.response.set_cookie(_COOKIE_NAME, cookie, max_age=max_age)
user.password = '******'
return user

_RE_EMAIL = re.compile(r'^[a-z0-9\.\-\_]+\@[a-z0-9\-\_]+(\.[a-z0-9\-\_]+){1,4}$')
_RE_MD5 = re.compile(r'^[0-9a-f]{32}$')

@api
@post('/api/users')
def register_user():
i = ctx.request.input(name='', email='', password='')
name = i.name.strip()
email = i.email.strip().lower()
password = i.password
if not name:
raise APIValueError('name')
if not email or not _RE_EMAIL.match(email):
raise APIValueError('email')
if not password or not _RE_MD5.match(password):
raise APIValueError('password')
user = User.find_first('where email=?', email)
if user:
raise APIError('register:failed', 'email', 'Email is already in use.')
user = User(name=name, email=email, password=password, image='http://www.gravatar.com/avatar/%s?d=mm&s=120' % hashlib.md5(email).hexdigest())
user.insert()
# make session cookie:
cookie = make_signed_cookie(user.id, user.password, None)
ctx.response.set_cookie(_COOKIE_NAME, cookie)
return user

@view('register.html')
@get('/register')
def register():
return dict()

@api
@get('/api/users')
def api_get_users():
users = User.find_by('order by created_at desc')
for u in users:
u.password = '******'
return dict(users=users)
42 changes: 20 additions & 22 deletions www/wsgiapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,20 @@

__author__ = 'Michael Liao'

"""
'''
A WSGI application entry.
"""
'''

import logging; logging.basicConfig(level=logging.INFO)

import os
import os, time
from datetime import datetime

from transwarp import db
from transwarp.web import WSGIApplication, Jinja2TemplateEngine

from config import configs

# init db:
db.create_engine(**configs.db)

# init wsgi app:
wsgi = WSGIApplication(os.path.dirname(os.path.abspath(__file__)))

template_engine = Jinja2TemplateEngine(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates'))

wsgi.template_engine = template_engine

# load module
import urls

wsgi.add_module(urls)

# jinja2 filter
import time, datetime
def datetime_filter(t):
delta = int(time.time() - t)
if delta < 60:
Expand All @@ -46,8 +30,22 @@ def datetime_filter(t):
dt = datetime.fromtimestamp(t)
return u'%s年%s月%s日' % (dt.year, dt.month, dt.day)

# init db:
db.create_engine(**configs.db)

# init wsgi app:
wsgi = WSGIApplication(os.path.dirname(os.path.abspath(__file__)))

template_engine = Jinja2TemplateEngine(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates'))
template_engine.add_filter('datetime', datetime_filter)

if __name__ == '__main__':
wsgi.run(port=9000, host='0.0.0.0')
wsgi.template_engine = template_engine

import urls

wsgi.add_interceptor(urls.user_interceptor)
wsgi.add_interceptor(urls.manage_interceptor)
wsgi.add_module(urls)

if __name__ == '__main__':
wsgi.run(9000, host='0.0.0.0')

0 comments on commit 8a92f60

Please sign in to comment.