Skip to content

Commit

Permalink
Resolve merge from feature/auth
Browse files Browse the repository at this point in the history
  • Loading branch information
mitechie committed Jun 18, 2011
2 parents 8f97125 + a18a29a commit e270d7c
Show file tree
Hide file tree
Showing 58 changed files with 2,113 additions and 739 deletions.
2 changes: 0 additions & 2 deletions COPYING
Expand Up @@ -615,5 +615,3 @@ reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

END OF TERMS AND CONDITIONS
27 changes: 24 additions & 3 deletions bookie/__init__.py
@@ -1,20 +1,41 @@
from pyramid.authentication import AuthTktAuthenticationPolicy
from pyramid.authorization import ACLAuthorizationPolicy
from pyramid.config import Configurator
from pyramid.session import UnencryptedCookieSessionFactoryConfig
from sqlalchemy import engine_from_config

from bookie.lib.access import RequestWithUserAttribute
from bookie.models import initialize_sql
from bookie.models.auth import UserMgr
from bookie.routes import build_routes

from pyramid.security import Allow
from pyramid.security import Everyone
from pyramid.security import ALL_PERMISSIONS


class RootFactory(object):
__acl__ = [ (Allow, Everyone, ALL_PERMISSIONS)]

def __init__(self, request):
self.__dict__.update(request.matchdict)


def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
engine = engine_from_config(settings, 'sqlalchemy.')
initialize_sql(engine)

unencrypt = UnencryptedCookieSessionFactoryConfig('itsaseekreet')
authn_policy = AuthTktAuthenticationPolicy(settings.get('auth.secret'),
callback=UserMgr.auth_groupfinder)
authz_policy = ACLAuthorizationPolicy()

config = Configurator(settings=settings,
root_factory='bookie.RootFactory',
authentication_policy=authn_policy,
authorization_policy=authz_policy)
config.set_request_factory(RequestWithUserAttribute)

config = Configurator(settings=settings, session_factory=unencrypt)
config = build_routes(config)
config.add_static_view('static', 'bookie:static')
config.scan('bookie.views')
Expand Down
66 changes: 55 additions & 11 deletions bookie/lib/access.py
@@ -1,17 +1,22 @@
"""Handle auth and authz activities in bookie"""
import logging

from pyramid.decorator import reify
from pyramid.httpexceptions import HTTPForbidden
from pyramid.settings import asbool
from pyramid.request import Request
from pyramid.security import unauthenticated_userid

from bookie.models.auth import UserMgr


LOG = logging.getLogger(__name__)


class Authorize(object):
class ApiAuthorize(object):
"""Context manager to check if the user is authorized
use:
with Authorize(some_key):
with ApiAuthorize(some_key):
# do work
Will return NotAuthorized if it fails
Expand All @@ -34,17 +39,56 @@ def __exit__(self, exc_type, exc_value, traceback):
"""No cleanup work to do after usage"""
pass

def edit_enabled(settings):
"""Is the config .ini setting for allowing edit enabled?
class ReqAuthorize(object):
"""Context manager to check if the user is logged in
If the .ini setting for ui edits is not true, then no authed
use:
with ReqAuthorize(request):
# do work
Will return NotAuthorized if it fails
"""
allow_edit = asbool(settings.get('allow_edit', False))

if allow_edit:
return True
else:
return False
def __init__(self, request, username=None):
"""Create the context manager"""
LOG.debug('USER')
LOG.debug(request.user)

self.request = request
self.username = username

def __enter__(self):
"""Verify api key set in constructor"""
if self.request.user is None:
LOG.error('Invalid Request: Not Logged in!')
raise HTTPForbidden('Invalid Authorization')

# if we have a username we're told to check against, make sure the
# username matches
if self.username is not None and self.username != self.request.user.username:
LOG.error('Invalid Request: Wrong Username!')
raise HTTPForbidden('Invalid Authorization')

def __exit__(self, exc_type, exc_value, traceback):
"""No cleanup work to do after usage"""
pass


class RequestWithUserAttribute(Request):
@reify
def user(self):
# <your database connection, however you get it, the below line
# is just an example>
# dbconn = self.registry.settings['dbconn']
LOG.debug('in Request with Attribute')
user_id = unauthenticated_userid(self)
LOG.debug(user_id)
if user_id is not None:
LOG.debug('user_id is not none')

# this should return None if the user doesn't exist
# in the database
user = UserMgr.get(user_id=user_id)
LOG.debug(user)
return user
5 changes: 3 additions & 2 deletions bookie/lib/importer.py
Expand Up @@ -8,9 +8,10 @@
class Importer(object):
"""The actual factory object we use for handling imports"""

def __init__(self, import_io):
def __init__(self, import_io, username=None):
"""work on getting an importer instance"""
self.file_handle = import_io
self.username = username

def __new__(cls, *args, **kwargs):
"""Overriding new we return a subclass based on the file content"""
Expand Down Expand Up @@ -42,7 +43,7 @@ def save_bookmark(self, url, desc, ext, tags, dt=None, fulltext=None):
:param fulltext: Fulltext handler instance used to store that info
"""
BmarkMgr.store(url, desc, ext, tags, dt=dt, fulltext=fulltext)
BmarkMgr.store(url, self.username, desc, ext, tags, dt=dt, fulltext=fulltext)


class DelImporter(Importer):
Expand Down
57 changes: 45 additions & 12 deletions bookie/models/__init__.py
Expand Up @@ -151,14 +151,20 @@ def from_string(tag_str):
return tag_objects

@staticmethod
def find(order_by=None, tags=None):
def find(order_by=None, tags=None, username=None):
"""Find all of the tags in the system"""
qry = Tag.query

if tags:
# limit to only the tag names in this list
qry = qry.filter(Tag.name.in_(tags))

if username:
# then we'll need to bind to bmarks to be able to limit on the
# username field
bmark = aliased(Bmark)
qry = qry.join((bmark, Tag.bmark)).filter(bmark.username==username)

if order_by is not None:
qry = qry.order_by(order_by)
else:
Expand Down Expand Up @@ -388,28 +394,43 @@ class BmarkMgr(object):
"""Class to handle non-instance Bmark functions"""

@staticmethod
def get_by_url(url):
def get_by_url(url, username=None):
"""Get a bmark from the system via the url"""
# normalize the url
clean_url = BmarkTools.normalize_url(url)
return Bmark.query.join(Bmark.hashed).\

qry = Bmark.query.join(Bmark.hashed).\
options(contains_eager(Bmark.hashed)).\
filter(Hashed.url == clean_url).one()
filter(Hashed.url == clean_url)

if username:
qry = qry.filter(Bmark.username==username)

return qry.one()

@staticmethod
def get_by_hash(hash_id):
def get_by_hash(hash_id, username=None):
"""Get a bmark from the system via the hash_id"""
# normalize the url
return Bmark.query.join(Bmark.hashed).\
qry = Bmark.query.join(Bmark.hashed).\
options(contains_eager(Bmark.hashed)).\
filter(Hashed.hash_id == hash_id).first()
filter(Hashed.hash_id == hash_id)

if username:
qry = qry.filter(Bmark.username == username)

return qry.first()

@staticmethod
def find(limit=50, order_by=None, page=0, tags=None, with_tags=True):
def find(limit=50, order_by=None, page=0, tags=None, with_tags=True,
username=None):
"""Search for specific sets of bookmarks"""
qry = Bmark.query
offset = limit * page

if username:
qry = qry.filter(Bmark.username == username)

if order_by is None:
order_by = Bmark.stored.desc()

Expand Down Expand Up @@ -495,7 +516,7 @@ def popular(limit=50, page=0, with_tags=False):
return res

@staticmethod
def store(url, desc, ext, tags, dt=None, fulltext=None):
def store(url, username, desc, ext, tags, dt=None, fulltext=None):
"""Store a bookmark
:param url: bookmarked url
Expand All @@ -506,6 +527,7 @@ def store(url, desc, ext, tags, dt=None, fulltext=None):
"""
mark = Bmark(url,
username,
desc=desc,
ext=ext,
tags=tags,
Expand All @@ -524,9 +546,14 @@ def store(url, desc, ext, tags, dt=None, fulltext=None):
return mark

@staticmethod
def hash_list():
def hash_list(username=None):
"""Get a list of the hash_ids we have stored"""
return DBSession.query(Bmark.hash_id).all()
qry = DBSession.query(Bmark.hash_id)

if username:
qry = qry.filter(Bmark.username==username)

return qry.all()


class BmarkTools(object):
Expand Down Expand Up @@ -560,6 +587,8 @@ class Bmark(Base):
stored = Column(DateTime, default=datetime.now)
updated = Column(DateTime, onupdate=datetime.now)
clicks = Column(Integer, default=0)
username = Column(Unicode(255), ForeignKey('users.username'),
nullable=False,)

# DON"T USE
tag_str = Column(UnicodeText())
Expand All @@ -579,7 +608,10 @@ class Bmark(Base):
single_parent=True,
)

def __init__(self, url, desc=None, ext=None, tags=None):
user = relation("User",
backref="bmark")

def __init__(self, url, username, desc=None, ext=None, tags=None):
"""Create a new bmark instance
:param url: string of the url to be added as a bookmark
Expand All @@ -597,6 +629,7 @@ def __init__(self, url, desc=None, ext=None, tags=None):
else:
self.hashed = existing

self.username = username
self.description = desc
self.extended = ext

Expand Down

0 comments on commit e270d7c

Please sign in to comment.