1#!/usr/bin/env python 2# 3# Copyright (C) 2013 Federico Ceratto and others, see AUTHORS file. 4# Released under GPLv3+ license, see LICENSE.txt 5# 6# Cork example web application 7# 8# The following users are already available: 9# admin/admin, demo/demo 10 11import bottle 12from beaker.middleware import SessionMiddleware 13from cork import Cork 14from cork.backends import SQLiteBackend 15import logging 16 17logging.basicConfig(format='localhost - - [%(asctime)s] %(message)s', level=logging.DEBUG) 18log = logging.getLogger(__name__) 19bottle.debug(True) 20 21def populate_backend(): 22 b = SQLiteBackend('example.db', initialize=True) 23 b.connection.executescript(""" 24 INSERT INTO users (username, email_addr, desc, role, hash, creation_date) VALUES 25 ( 26 'admin', 27 'admin@localhost.local', 28 'admin test user', 29 'admin', 30 'cLzRnzbEwehP6ZzTREh3A4MXJyNo+TV8Hs4//EEbPbiDoo+dmNg22f2RJC282aSwgyWv/O6s3h42qrA6iHx8yfw=', 31 '2012-10-28 20:50:26.286723' 32 ); 33 INSERT INTO roles (role, level) VALUES ('special', 200); 34 INSERT INTO roles (role, level) VALUES ('admin', 100); 35 INSERT INTO roles (role, level) VALUES ('editor', 60); 36 INSERT INTO roles (role, level) VALUES ('user', 50); 37 """) 38 return b 39 40b = populate_backend() 41aaa = Cork(backend=b, email_sender='federico.ceratto@gmail.com', smtp_url='smtp://smtp.magnet.ie') 42 43 44 45app = bottle.app() 46session_opts = { 47 'session.cookie_expires': True, 48 'session.encrypt_key': 'please use a random key and keep it secret!', 49 'session.httponly': True, 50 'session.timeout': 3600 * 24, # 1 day 51 'session.type': 'cookie', 52 'session.validate_key': True, 53} 54app = SessionMiddleware(app, session_opts) 55 56 57# # Bottle methods # # 58 59def postd(): 60 return bottle.request.forms 61 62 63def post_get(name, default=''): 64 return bottle.request.POST.get(name, default).strip() 65 66 67@bottle.post('/login') 68def login(): 69 """Authenticate users""" 70 username = post_get('username') 71 password = post_get('password') 72 aaa.login(username, password, success_redirect='/', fail_redirect='/login') 73 74@bottle.route('/user_is_anonymous') 75def user_is_anonymous(): 76 if aaa.user_is_anonymous: 77 return 'True' 78 79 return 'False' 80 81@bottle.route('/logout') 82def logout(): 83 aaa.logout(success_redirect='/login') 84 85 86@bottle.post('/register') 87def register(): 88 """Send out registration email""" 89 aaa.register(post_get('username'), post_get('password'), post_get('email_address')) 90 return 'Please check your mailbox.' 91 92 93@bottle.route('/validate_registration/:registration_code') 94def validate_registration(registration_code): 95 """Validate registration, create user account""" 96 aaa.validate_registration(registration_code) 97 return 'Thanks. <a href="/login">Go to login</a>' 98 99 100@bottle.post('/reset_password') 101def send_password_reset_email(): 102 """Send out password reset email""" 103 aaa.send_password_reset_email( 104 username=post_get('username'), 105 email_addr=post_get('email_address') 106 ) 107 return 'Please check your mailbox.' 108 109 110@bottle.route('/change_password/:reset_code') 111@bottle.view('password_change_form') 112def change_password(reset_code): 113 """Show password change form""" 114 return dict(reset_code=reset_code) 115 116 117@bottle.post('/change_password') 118def change_password(): 119 """Change password""" 120 aaa.reset_password(post_get('reset_code'), post_get('password')) 121 return 'Thanks. <a href="/login">Go to login</a>' 122 123 124@bottle.route('/') 125def index(): 126 """Only authenticated users can see this""" 127 aaa.require(fail_redirect='/login') 128 return 'Welcome! <a href="/admin">Admin page</a> <a href="/logout">Logout</a>' 129 130 131@bottle.route('/restricted_download') 132def restricted_download(): 133 """Only authenticated users can download this file""" 134 aaa.require(fail_redirect='/login') 135 return bottle.static_file('static_file', root='.') 136 137 138@bottle.route('/my_role') 139def show_current_user_role(): 140 """Show current user role""" 141 session = bottle.request.environ.get('beaker.session') 142 print "Session from simple_webapp", repr(session) 143 aaa.require(fail_redirect='/login') 144 return aaa.current_user.role 145 146 147# Admin-only pages 148 149@bottle.route('/admin') 150@bottle.view('admin_page') 151def admin(): 152 """Only admin users can see this""" 153 aaa.require(role='admin', fail_redirect='/sorry_page') 154 return dict( 155 current_user=aaa.current_user, 156 users=aaa.list_users(), 157 roles=aaa.list_roles() 158 ) 159 160 161@bottle.post('/create_user') 162def create_user(): 163 try: 164 aaa.create_user(postd().username, postd().role, postd().password) 165 return dict(ok=True, msg='') 166 except Exception, e: 167 return dict(ok=False, msg=e.message) 168 169 170@bottle.post('/delete_user') 171def delete_user(): 172 try: 173 aaa.delete_user(post_get('username')) 174 return dict(ok=True, msg='') 175 except Exception, e: 176 print repr(e) 177 return dict(ok=False, msg=e.message) 178 179 180@bottle.post('/create_role') 181def create_role(): 182 try: 183 aaa.create_role(post_get('role'), post_get('level')) 184 return dict(ok=True, msg='') 185 except Exception, e: 186 return dict(ok=False, msg=e.message) 187 188 189@bottle.post('/delete_role') 190def delete_role(): 191 try: 192 aaa.delete_role(post_get('role')) 193 return dict(ok=True, msg='') 194 except Exception, e: 195 return dict(ok=False, msg=e.message) 196 197 198# Static pages 199 200@bottle.route('/login') 201@bottle.view('login_form') 202def login_form(): 203 """Serve login form""" 204 return {} 205 206 207@bottle.route('/sorry_page') 208def sorry_page(): 209 """Serve sorry page""" 210 return '<p>Sorry, you are not authorized to perform this action</p>' 211 212 213# # Web application main # # 214 215def main(): 216 217 # Start the Bottle webapp 218 bottle.debug(True) 219 bottle.run(app=app, quiet=False, reloader=False) 220 221if __name__ == "__main__": 222 main() 223