diff --git a/ordr2/schemas/__init__.py b/ordr2/schemas/__init__.py new file mode 100644 index 0000000..fd7c18e --- /dev/null +++ b/ordr2/schemas/__init__.py @@ -0,0 +1,26 @@ +import colander +import deform + +from .helpers import ( + deferred_csrf_default, + deferred_csrf_validator + ) + + +# Base Schema + +class CSRFSchema(colander.Schema): + ''' base class for schemas with csrf validation ''' + csrf_token = colander.SchemaNode( + colander.String(), + default=deferred_csrf_default, + validator=deferred_csrf_validator, + widget=deform.widget.HiddenWidget(), + ) + + @classmethod + def as_form(cls, request, url, **kw): + schema = cls().bind(request=request) + form = deform.Form(schema, action=url, **kw) + return form + diff --git a/ordr2/schemas/account.py b/ordr2/schemas/account.py new file mode 100644 index 0000000..ab0f812 --- /dev/null +++ b/ordr2/schemas/account.py @@ -0,0 +1,30 @@ +import colander +import deform + +from . import CSRFSchema +from .helpers import deferred_unique_email_validator + + +# schema for user registration + +class RegistrationSchema(CSRFSchema): + ''' new user registration ''' + + user_name = colander.SchemaNode( + colander.String(), + widget=deform.widget.TextInputWidget(readonly=True), + ) + first_name = colander.SchemaNode( + colander.String() + ) + last_name = colander.SchemaNode( + colander.String() + ) + email = colander.SchemaNode( + colander.String(), + validator=deferred_unique_email_validator + ) + password = colander.SchemaNode( + colander.String(), + widget=deform.widget.CheckedPasswordWidget() + ) diff --git a/ordr2/schemas/helpers.py b/ordr2/schemas/helpers.py new file mode 100644 index 0000000..05887d0 --- /dev/null +++ b/ordr2/schemas/helpers.py @@ -0,0 +1,39 @@ +import colander +import deform + +from pyramid.csrf import get_csrf_token, check_csrf_token + +from ordr2.models import User + + +@colander.deferred +def deferred_csrf_default(node, kw): + ''' sets the current csrf token ''' + request = kw.get('request') + return get_csrf_token(request) + + +@colander.deferred +def deferred_csrf_validator(node, kw): + ''' validates a submitted csrf token ''' + def validate_csrf(node, value): + request = kw.get('request') + if not check_csrf_token(request, raises=False): + raise colander.Invalid(node, 'Bad CSRF token') + return validate_csrf + + +@colander.deferred +def deferred_unique_email_validator(node, kw): + ''' checks if an email is not registered already ''' + email_validator = colander.Email() + + def validate_unique_email(node, value): + email_validator(node, value) # raises exception on invalid address + request = kw.get('request') + user = request.dbsession.query(User).filter_by(email=value).first() + if user is not None: + raise colander.Invalid(node, 'Email address in use') + return validate_unique_email + +