Skip to content
This repository has been archived by the owner on Sep 28, 2022. It is now read-only.

Commit

Permalink
Merge pull request #75 from postatum/97933880_simplify_nefex
Browse files Browse the repository at this point in the history
Refactoring according to nef-example simplification
  • Loading branch information
jstoiko committed Jul 16, 2015
2 parents cd5b5e1 + 353cc8b commit 3f65321
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 90 deletions.
20 changes: 19 additions & 1 deletion nefertari/acl.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ class AuthenticatedReadACL(BaseACL):
Gives read access to all Authenticated users.
Gives delete, create, update access to admin only.
"""

def __init__(self, request):
super(AuthenticatedReadACL, self).__init__(request)
self.acl = (Allow, Authenticated, ['index', 'collection_options'])
Expand All @@ -114,3 +113,22 @@ def context_acl(self, obj):
(Allow, 'g:admin', ALL_PERMISSIONS),
(Allow, Authenticated, ['show', 'item_options']),
]


class AuthenticationACL(BaseACL):
""" Special ACL factory to be used with authentication views
(login, logout, register, etc.)
Allows 'create', 'show' and option methods to everyone.
"""
def __init__(self, request):
super(AuthenticationACL, self).__init__(request)
self.acl = (Allow, Everyone, [
'create', 'show', 'collection_options', 'item_options'])

def context_acl(self, obj):
return [
(Allow, 'g:admin', ALL_PERMISSIONS),
(Allow, Everyone, [
'create', 'show', 'collection_options', 'item_options']),
]
59 changes: 26 additions & 33 deletions nefertari/authentication/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,24 @@
crypt = cryptacular.bcrypt.BCRYPTPasswordManager()


class AuthModelDefaultMixin(object):
class AuthModelMethodsMixin(object):
""" Mixin that implements all methods required for Ticket and Token
auth systems to work.
All implemented methods must be class methods.
"""
@classmethod
def get_resource(self, *args, **kwargs):
return super(AuthModelDefaultMixin, self).get_resource(
return super(AuthModelMethodsMixin, self).get_resource(
*args, **kwargs)

@classmethod
def pk_field(self, *args, **kwargs):
return super(AuthModelDefaultMixin, self).pk_field(*args, **kwargs)
return super(AuthModelMethodsMixin, self).pk_field(*args, **kwargs)

@classmethod
def get_or_create(self, *args, **kwargs):
return super(AuthModelDefaultMixin, self).get_or_create(
return super(AuthModelMethodsMixin, self).get_or_create(
*args, **kwargs)

@classmethod
Expand Down Expand Up @@ -151,44 +151,37 @@ def lower_strip(instance, new_value):
return (new_value or '').lower().strip()


def random_uuid(instance, new_value):
return new_value or uuid.uuid4().hex


def encrypt_password(instance, new_value):
""" Crypt :new_value: if it's not crypted yet. """
if new_value and not crypt.match(new_value):
new_value = str(crypt.encode(new_value))
return new_value


def get_authuser_model():
""" Define and return AuthModel model class.
class AuthUserMixin(AuthModelMethodsMixin):
""" Mixin that may be used as base for auth User models.
Wrapped in function to avoid unnecessary DB tables creation.
Implements basic operations to support Pyramid Ticket-based and custom
ApiKey token-based authentication.
"""

class AuthUser(AuthModelDefaultMixin, engine.BaseDocument):
""" Class that is meant to be User class in Auth system.
Implements basic operations to support Pyramid Ticket-based and custom
ApiKey token-based authentication.
"""
__tablename__ = 'nefertari_authuser'

id = engine.IdField(primary_key=True)

username = engine.StringField(
min_length=1, max_length=50, unique=True, required=True,
before_validation=[lower_strip])
email = engine.StringField(
unique=True, required=True,
before_validation=[lower_strip])
password = engine.StringField(
min_length=3, required=True,
after_validation=[encrypt_password])

groups = engine.ListField(
item_type=engine.StringField,
choices=['admin', 'user'], default=['user'])

return AuthUser
id = engine.IdField()
username = engine.StringField(
primary_key=True, unique=True,
min_length=1, max_length=50,
before_validation=[random_uuid, lower_strip])
email = engine.StringField(
unique=True, required=True,
before_validation=[lower_strip])
password = engine.StringField(
min_length=3, required=True,
after_validation=[encrypt_password])
groups = engine.ListField(
item_type=engine.StringField,
choices=['admin', 'user'], default=['user'])


def create_apikey_token():
Expand Down
84 changes: 79 additions & 5 deletions nefertari/authentication/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from nefertari.view import BaseView


class TicketAuthenticationView(BaseView):
""" View for auth operations to use with Pyramid ticket-based auth.
class TicketAuthViewMixin(object):
""" View mixin for auth operations to use with Pyramid ticket-based auth.
`login` (POST): Login the user with 'login' and 'password'
`logout`: Logout user
"""
Expand All @@ -26,8 +26,7 @@ def register(self):
def login(self, **params):
self._json_params.update(params)
next = self._query_params.get('next', '')
login_url = self.request.route_url('login')
if next.startswith(login_url):
if self.request.path in next:
next = '' # never use the login form itself as next

unauthorized_url = self._query_params.get('unauthorized', None)
Expand Down Expand Up @@ -57,7 +56,46 @@ def logout(self):
return JHTTPOk('Logged out', headers=headers)


class TokenAuthenticationView(BaseView):
class TicketAuthRegisterView(TicketAuthViewMixin, BaseView):
""" Ticket auth register view.
Register with::
root = config.get_root_resource()
root.add('account', view='path.to.TicketAuthRegisterView',
factory='nefertari.acl.AuthenticationACL')
"""
def create(self, *args, **kwargs):
return self.register(*args, **kwargs)


class TicketAuthLoginView(TicketAuthViewMixin, BaseView):
""" Ticket auth login view.
Register with::
root = config.get_root_resource()
root.add('login', view='path.to.TicketAuthLoginView',
factory='nefertari.acl.AuthenticationACL')
"""
def create(self, *args, **kwargs):
return self.login(*args, **kwargs)


class TicketAuthLogoutView(TicketAuthViewMixin, BaseView):
""" Ticket auth logout view. Allows logout on GET and POST.
Register with::
root = config.get_root_resource()
root.add('logout', view='path.to.TicketAuthLogoutView',
factory='nefertari.acl.AuthenticationACL')
"""
def create(self, *args, **kwargs):
return self.logout(*args, **kwargs)

def show(self, *args, **kwargs):
return self.logout(*args, **kwargs)


class TokenAuthViewMixin(object):
""" View for auth operations to use with
`nefertari.authentication.policies.ApiKeyAuthenticationPolicy`
token-based auth. Implements methods:
Expand Down Expand Up @@ -109,3 +147,39 @@ def reset_token(self, **params):
self.user.api_key.reset_token()
headers = remember(self.request, self.user.username)
return JHTTPOk('Registered', headers=headers)


class TokenAuthRegisterView(TokenAuthViewMixin, BaseView):
""" Token auth register view.
Register with::
root = config.get_root_resource()
root.add('register', view='path.to.TokenAuthRegisterView',
factory='nefertari.acl.AuthenticationACL')
"""
def create(self, *args, **kwargs):
return self.register(*args, **kwargs)


class TokenAuthClaimView(TokenAuthViewMixin, BaseView):
""" Ticket auth view to claim registered token.
Register with::
root = config.get_root_resource()
root.add('token', view='path.to.TokenAuthClaimView',
factory='nefertari.acl.AuthenticationACL')
"""
def create(self, *args, **kwargs):
return self.claim_token(*args, **kwargs)


class TokenAuthResetView(TokenAuthViewMixin, BaseView):
""" Ticket auth view to reset registered token.
Register with::
root = config.get_root_resource()
root.add('reset_token', view='path.to.TokenAuthResetView',
factory='nefertari.acl.AuthenticationACL')
"""
def create(self, *args, **kwargs):
return self.reset_token(*args, **kwargs)
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ def bootstrap(config):
config.include('nefertari.view')
config.include('nefertari.elasticsearch')

if Settings.asbool('debug'):
log.warning('*** DEBUG DEBUG DEBUG mode ***')
if Settings.asbool('enable_get_tunneling'):
log.warning('GET tunneling enabled')
config.add_tween('nefertari.tweens.get_tunneling')

def _route_url(request, route_name, *args, **kw):
Expand Down
2 changes: 1 addition & 1 deletion nefertari/scaffolds/nefertari_starter/local.ini_tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use = egg:{{package}}

# Nefertari
nefertari.engine = nefertari_{{engine}}
debug = true
enable_get_tunneling = true

# SQLA
sqlalchemy.url = postgresql://%(host)s:5432/{{package}}
Expand Down
7 changes: 0 additions & 7 deletions nefertari/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,6 @@ def convert_ids2objects(self, model_cls=None):
rel_model_cls = engine.get_relationship_cls(field, model_cls)
self.id2obj(field, rel_model_cls)

def get_debug(self, package=None):
if not package:
key = 'debug'
else:
key = '%s.debug' % package.split('.')[0]
return asbool(self.request.registry.settings.get(key))

def setup_default_wrappers(self):
""" Setup defaulf wrappers.
Expand Down

0 comments on commit 3f65321

Please sign in to comment.