Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix for encoding problem #118

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions brubeck/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.DS_Store
*.db
*.pyc
*.bak
*.log
*.*~
MANIFEST
build
dist
.rope*
*.pid
.*.swp
.*.swo
*.egg-info
.tox
File renamed without changes.
81 changes: 81 additions & 0 deletions brubeck/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# What Is Brubeck?

__Brubeck__ is a flexible Python web framework that aims to make the process of building scalable web services easy.

Brubeck's design is discussed in depth in the provided documentation. There, you will find lots of code samples for building request handlers, authentication, rendering templates, managing databases and more.


## Goals

* __Be Fast__: Brubeck is currently very fast. We intend to keep it that way.

* __Scalable__: Massive scaling capabilities should be available out of the box.

* __Friendly__: Should be easy for Python hackers of any skill level to use.

* __Pluggable__: Brubeck can speak to any language and any database.


# Example: Hello World

This is a whole Brubeck application.

class DemoHandler(WebMessageHandler):
def get(self):
self.set_body('Hello world')
return self.render()

urls = [(r'^/', DemoHandler)]
msg_conn = Mongrel2Connection('ipc://127.0.0.1:9999',
'ipc://127.0.0.1:9998')

app = Brubeck(msg_conn=msg_conn,
handler_tuples=urls)
app.run()


# Complete Examples

__Listsurf__ is a simple to way to save links. Yeah... another delicious clone!

It serves as a basic demonstration of what a complete site looks like when you build with Brubeck. It has authentication with secure cookies, offers a JSON API, uses [Jinja2](http://jinja.pocoo.org/) for templating and stores data in [MongoDB](http://mongodb.org).

* [Listsurf Code](https://github.com/j2labs/listsurf)

__Readify__ is a more elaborate form of Listsurf.

User's have profiles, you can mark things as liked, archived (out of your stream, kept) or you can delete them. The links can also be tagged for easy finding. This project also splits the API out from the Web system into two separate processes, each reading from a single Mongrel2.

You could actually run four Web processes and four API processes as easily as just turning each of them on four times.

This project roughly represents a typical organization of Brubeck's components. Most notably is the separation of handlers, models and queries into isolated python files.

* [Readify Code](https://github.com/j2labs/readify)

__SpotiChat__ is a chat app for spotify user.

SpotiChat provides chat for users listening to the same song with Spotify. The chat is handled via request handlers that go to sleep until incoming messages need to be distributed to connect clients. The messages are backed by [Redis](http://redis.io) too.

* [SpotiChat Code](https://github.com/sethmurphy/SpotiChat-Server)

__no.js__ is a javascript-free chat system.

It works by using the old META Refresh trick, combined with long-polling. It even works in IE4!

* [No.js Code](https://github.com/talos/no.js)


## Contributors

Brubeck wouldn't be what it is without help from:

[James Dennis](https://github.com/j2labs), [Andrew Gwozdziewycz](https://github.com/apgwoz), [Malcolm Matalka](https://github.com/orbitz/), [Dion Paragas](https://github.com/d1on/), [Duane Griffin](https://github.com/duaneg), [Faruk Akgul](https://github.com/faruken), [Seth Murphy](https://github.com/sethmurphy), [John Krauss](https://github.com/talos), [Ben Beecher](https://github.com/gone), [Jordan Orelli](https://github.com/jordanorelli), [Michael Larsen](https://github.com/mghlarsen), [Moritz](https://github.com/m2w), [Dmitrijs Milajevs](https://github.com/dimazest), [Paul Winkler](https://github.com/slinkp), [Chris McCulloh](https://github.com/st0w), [Nico Mandery](https://github.com/nmandery), [Victor Trac](https://github.com/victortrac)


# Contact Us

If you discover bugs or want to suggest features, please use our [issue tracker](https://github.com/j2labs/brubeck/issues).

Also consider joining our mailing list: [brubeck-dev](http://groups.google.com/group/brubeck-dev).

You can find some of us in #brubeck on freenode too.
2 changes: 1 addition & 1 deletion brubeck/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def gen_hexdigest(raw_password, algorithm=BCRYPT, salt=None):
# bcrypt has a special salt
if salt is None:
salt = bcrypt.gensalt()
return (algorithm, salt, bcrypt.hashpw(raw_password, salt))
return (algorithm, salt, bcrypt.hashpw(raw_password.encode('utf-8'), salt.encode('utf-8')))
raise ValueError('Unknown password algorithm')


Expand Down
16 changes: 16 additions & 0 deletions brubeck/brubeck/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env python

"""The Brubeck Message Handling system."""

version = "0.4.0"
version_info = (0, 4, 0)
__all__ = ['auth',
'autoapi',
'caching',
'datamosh',
'models',
'mongrel2',
'queryset',
'request_handling',
'templating',
'timekeeping']
134 changes: 134 additions & 0 deletions brubeck/brubeck/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
"""Authentication functions are offered here in three groups.

1. The mechanics of auth, like generating a hex digest or assembling the
data.

2. Tools for applying auth requirements to functions, eg. decorators.

3. Mixins for adding authenticaiton handling to MessageHandler's and
Document classes
"""

import bcrypt
import functools
import logging


###
### Password Helpers
###

BCRYPT = 'bcrypt'
PASSWD_DELIM = '|||'


def gen_hexdigest(raw_password, algorithm=BCRYPT, salt=None):
"""Takes the algorithm, salt and password and uses Python's
hashlib to produce the hash. Currently only supports bcrypt.
"""
if raw_password is None:
raise ValueError('No empty passwords, fool')
if algorithm == BCRYPT:
# bcrypt has a special salt
if salt is None:
salt = bcrypt.gensalt()
return (algorithm, salt, bcrypt.hashpw(raw_password.encode('utf-8'), salt.encode('utf-8')))
raise ValueError('Unknown password algorithm')


def build_passwd_line(algorithm, salt, digest):
"""Simply takes the inputs for a passwd entry and puts them
into the convention for storage
"""
return PASSWD_DELIM.join([algorithm, salt, digest])


def split_passwd_line(password_line):
"""Takes a password line and returns the line split by PASSWD_DELIM
"""
return password_line.split(PASSWD_DELIM)


###
### Authentication decorators
###

def authenticated(method):
"""Decorate request handler methods with this to require that the user be
logged in. Works by checking for the existence of self.current_user as set
by a RequestHandler's prepare() function.
"""
@functools.wraps(method)
def wrapper(self, *args, **kwargs):
if not self.current_user:
return self.render_error(self._AUTH_FAILURE, self.auth_error)
return method(self, *args, **kwargs)
return wrapper


def web_authenticated(method):
"""Same as `authenticated` except it redirects a user to the login page
specified by self.application.login_url
"""
@functools.wraps(method)
def wrapper(self, *args, **kwargs):
if not self.current_user:
has_login_url = hasattr(self.application, 'login_url')
if has_login_url and self.application.login_url is not None:
return self.redirect(self.application.login_url)
else:
error = 'web_authentication called with undefined <login_url>'
logging.error(error)
return self.render_error(self._AUTH_FAILURE)
return method(self, *args, **kwargs)
return wrapper


###
### Mixins to extend MessageHandlers with auth funcitons
###

class UserHandlingMixin(object):
"""A request handler that uses this mixin can also use the decorators
above. This mixin is intended to make the interaction with authentication
generic without insisting on a particular strategy.
"""

@property
def current_user(self):
"""The authenticated user for this message.

Determined by either get_current_user, which you can override to
set the user based on, e.g., a cookie. If that method is not

overridden, this method always returns None.

We lazy-load the current user the first time this method is called
and cache the result after that.
"""
if not hasattr(self, "_current_user"):
self._current_user = self.get_current_user()
return self._current_user

def get_current_user(self):
"""Override to determine the current user from, e.g., a cookie.
"""
return None

@property
def current_userprofile(self):
"""Same idea for the user's profile
"""
if not hasattr(self, "_current_userprofile"):
self._current_userprofile = self.get_current_userprofile()
return self._current_userprofile

def get_current_userprofile(self):
"""Override to determine the current user
"""
return None

def auth_error(self):
"""Override with actions to perform before rendering the error output.
"""
pass
Loading