Exemple #1
0
def _update_subscription_data(request, subscription):
    """
    Update the subscriptions in the database from form data.

    Using data from the passed subscription struct, find a subscription in the
    database, and update it (if it belongs to the current logged-in user).
    """
    sub = Subscriptions.get_by_id(subscription['id'])
    if sub is None:
        return {
            'errors': {'subscriptions': _('Subscription not found')},
        }

    # If we're trying to update a subscription for anyone other than
    # the currently logged-in user, bail fast.
    #
    # The error message is deliberately identical to the one above, so
    # as not to leak any information about who which subscription ids
    # belong to.
    if sub.uri != request.authenticated_userid:
        return {
            'errors': {'subscriptions': _('Subscription not found')},
        }

    sub.active = subscription.get('active', True)

    request.session.flash(_('Changes saved!'), 'success')
Exemple #2
0
Fichier : views.py Projet : pamo/h
    def check_credentials(self, username, password):
        allow_email_auth = self.settings.get('horus.allow_email_auth', False)

        user = self.User.get_by_username(self.request, username)

        if allow_email_auth and not user:
            user = self.User.get_by_email(self.request, username)

        if not user:
            raise httpexceptions.HTTPBadRequest({
                'errors': [{
                    'username': _('User does not exist.'),
                }],
            })

        if not self.User.validate_user(user, password):
            raise httpexceptions.HTTPBadRequest({
                'errors': [{
                    'password': _('Incorrect password. Please try again.'),
                }],
            })

        if not self.allow_inactive_login and self.require_activation \
                and not user.is_activated:
            reason = _('Your account is not active, please check your e-mail.')
            raise httpexceptions.HTTPBadRequest({'reason': reason})

        return user
Exemple #3
0
    def validator(self, node, value):
        super(LoginSchema, self).validator(node, value)

        username = value.get('username')
        password = value.get('password')

        user = User.get_by_username(username)
        if user is None:
            user = User.get_by_email(username)

        if user is None:
            err = colander.Invalid(node)
            err['username'] = _('User does not exist.')
            raise err

        if not User.validate_user(user, password):
            err = colander.Invalid(node)
            err['password'] = _('Incorrect password. Please try again.')
            raise err

        if not user.is_activated:
            reason = _('Your account is not active. Please check your e-mail.')
            raise colander.Invalid(node, reason)

        value['user'] = user
Exemple #4
0
    def validator(self, node, value):
        super(LoginSchema, self).validator(node, value)

        username = value.get('username')
        password = value.get('password')

        user = User.get_by_username(username)
        if user is None:
            user = User.get_by_email(username)

        if user is None:
            err = colander.Invalid(node)
            err['username'] = _('User does not exist.')
            raise err

        if not User.validate_user(user, password):
            err = colander.Invalid(node)
            err['password'] = _('Incorrect password. Please try again.')
            raise err

        if not user.is_activated:
            reason = _('Your account is not active. Please check your e-mail.')
            raise colander.Invalid(node, reason)

        value['user'] = user
Exemple #5
0
    def edit_profile(self):
        """Handle POST payload from profile update form."""
        if self.request.method != 'POST':
            return httpexceptions.HTTPMethodNotAllowed()

        # Nothing to do here for non logged-in users
        if self.request.authenticated_userid is None:
            return httpexceptions.HTTPUnauthorized()

        err, appstruct = validate_form(self.form, self.request.POST.items())
        if err is not None:
            return err

        user = User.get_by_id(self.request, self.request.authenticated_userid)
        response = {'model': {'email': user.email}}

        # We allow updating subscriptions without validating a password
        subscriptions = appstruct.get('subscriptions')
        if subscriptions:
            data = json.loads(subscriptions)
            err = _update_subscription_data(self.request, data)
            if err is not None:
                return err
            return response

        # Any updates to fields below this point require password validation.
        #
        #   `pwd` is the current password
        #   `password` (used below) is optional, and is the new password
        #
        if not User.validate_user(user, appstruct.get('pwd')):
            return {'errors': {'pwd': _('Invalid password')}, 'code': 401}

        email = appstruct.get('email')
        if email:
            email_user = User.get_by_email(email)

            if email_user:
                if email_user.id != user.id:
                    return {
                        'errors': {'pwd': _('That email is already used')},
                    }

            response['model']['email'] = user.email = email

        password = appstruct.get('password')
        if password:
            user.password = password

        return response
Exemple #6
0
    def edit_profile(self):
        try:
            appstruct = _validate_edit_profile_request(self.request)
        except _InvalidEditProfileRequestError as err:
            return dict(errors=err.errors)

        username = appstruct['username']
        pwd = appstruct['pwd']
        subscriptions = appstruct['subscriptions']

        if subscriptions:
            # Update the subscriptions table
            subs = json.loads(subscriptions)
            if username == subs['uri']:
                s = Subscriptions.get_by_id(self.request, subs['id'])
                if s:
                    s.active = subs['active']
                    self.db.add(s)
                    return {}
                else:
                    return dict(
                        errors=[
                            {'subscriptions': _('Non existing subscription')}
                        ],
                        code=404
                    )
            else:
                return dict(
                    errors=[{'username': _('Invalid username')}], code=400
                )

        # Password check
        user = self.User.get_user(self.request, username, pwd)
        if user:
            self.request.context = user
            response = super(ProfileController, self).edit_profile()

            # Add the user's email into the model dict that eventually gets
            # returned to the browser. This is needed so that the edit profile
            # forms can show the value of the user's current email.
            if self.request.authenticated_userid:
                user = h.accounts.models.User.get_by_id(
                    self.request, self.request.authenticated_userid)
                response.json = {"model": {"email": user.email}}

            return response
        else:
            return dict(errors=[{'pwd': _('Invalid password')}], code=401)
Exemple #7
0
def email_exists(node, value):
    '''Colander validator that ensures a user with this email exists.'''
    user = User.get_by_email(value)
    if not user:
        msg = _('We have no user with the email address "{}". Try correcting '
                'this address or try another.')
        raise colander.Invalid(node, msg)
Exemple #8
0
 def logout(self):
     self.request.registry.notify(LogoutEvent(self.request))
     self.request.session.invalidate()
     self.request.session.flash(_('You have logged out.'), 'success')
     headers = forget(self.request)
     return httpexceptions.HTTPFound(location=self.logout_redirect,
                                     headers=headers)
Exemple #9
0
    def activate(self):
        request = self.request
        schema = request.registry.getUtility(interfaces.IActivateSchema)
        schema = schema().bind(request=self.request)
        form = request.registry.getUtility(interfaces.IActivateForm)(schema)

        appstruct = None
        result = None
        try:
            appstruct = form.validate(request.POST.items())
        except deform.ValidationFailure as e:
            result = dict(form=e.render(), errors=e.error.children)
        else:
            code = appstruct['code']
            activation = self.Activation.get_by_code(request, code)
            user = None
            if activation:
                user = self.User.get_by_activation(request, activation)

            request.user = user
            if user:
                user.password = appstruct['password']
                self.db.add(user)
                self.db.delete(activation)
                FlashMessage(request, self.Str.authenticated, kind='success')
            else:
                form.error = colander.Invalid(
                    form.schema,
                    _('This activation code is not valid.')
                )
                result = dict(form=form.render(), errors=[form.error])

        return self.respond(result)
Exemple #10
0
    def activate(self):
        request = self.request
        schema = request.registry.getUtility(interfaces.IActivateSchema)
        schema = schema().bind(request=self.request)
        form = request.registry.getUtility(interfaces.IActivateForm)(schema)

        appstruct = None
        result = None
        try:
            appstruct = form.validate(request.POST.items())
        except deform.ValidationFailure as e:
            result = dict(form=e.render(), errors=e.error.children)
        else:
            code = appstruct['code']
            activation = self.Activation.get_by_code(request, code)
            user = None
            if activation:
                user = self.User.get_by_activation(request, activation)

            request.user = user
            if user:
                user.password = appstruct['password']
                self.db.add(user)
                self.db.delete(activation)
                FlashMessage(request, self.Str.authenticated, kind='success')
            else:
                form.error = colander.Invalid(
                    form.schema, _('This activation code is not valid.'))
                result = dict(form=form.render(), errors=[form.error])

        return self.respond(result)
Exemple #11
0
def unique_email(node, value):
    '''Colander validator that ensures no user with this email exists.'''
    user = User.get_by_email(value)
    if user:
        msg = _("Sorry, an account with this email address already exists. "
                "Try logging in instead.")
        raise colander.Invalid(node, msg)
Exemple #12
0
def unique_username(node, value):
    '''Colander validator that ensures the username does not exist.'''
    user = User.get_by_username(value)
    if user:
        msg = _("Sorry, an account with this username already exists. "
                "Please enter another one.")
        raise colander.Invalid(node, msg)
Exemple #13
0
def unique_email(node, value):
    '''Colander validator that ensures no user with this email exists.'''
    user = User.get_by_email(value)
    if user:
        msg = _("Sorry, an account with this email address already exists. "
                "Try logging in instead.")
        raise colander.Invalid(node, msg)
Exemple #14
0
def bad_csrf_token(context, request):
    reason = _('Session is invalid. Please try again.')
    return {
        'status': 'failure',
        'reason': reason,
        'model': model(request),
    }
Exemple #15
0
def email_exists(node, value):
    '''Colander validator that ensures a user with this email exists.'''
    user = User.get_by_email(value)
    if not user:
        msg = _('We have no user with the email address "{}". Try correcting '
                'this address or try another.')
        raise colander.Invalid(node, msg)
Exemple #16
0
def unique_username(node, value):
    '''Colander validator that ensures the username does not exist.'''
    user = User.get_by_username(value)
    if user:
        msg = _("Sorry, an account with this username already exists. "
                "Please enter another one.")
        raise colander.Invalid(node, msg)
Exemple #17
0
def bad_csrf_token(context, request):
    reason = _('Session is invalid. Please try again.')
    return {
        'status': 'failure',
        'reason': reason,
        'model': model(request),
    }
Exemple #18
0
    def disable_user(self):
        """Disable the user by setting a random password."""
        err, appstruct = validate_form(self.form, self.request.POST.items())
        if err is not None:
            return err

        username = appstruct['username']
        pwd = appstruct['pwd']

        # Password check
        user = User.get_user(username, pwd)
        if user:
            # TODO: maybe have an explicit disabled flag in the status
            user.password = User.generate_random_password()
            self.request.session.flash(_('Account disabled.'), 'success')
            return {}
        else:
            return dict(errors={'pwd': _('Invalid password')}, code=401)
Exemple #19
0
def unblacklisted_username(node, value, blacklist=None):
    '''Colander validator that ensures the username is not blacklisted.'''
    if blacklist is None:
        blacklist = get_blacklist()
    if value.lower() in blacklist:
        # We raise a generic "user with this name already exists" error so as
        # not to make explicit the presence of a blacklist.
        msg = _("Sorry, an account with this username already exists. "
                "Please enter another one.")
        raise colander.Invalid(node, msg)
Exemple #20
0
def unblacklisted_username(node, value, blacklist=None):
    '''Colander validator that ensures the username is not blacklisted.'''
    if blacklist is None:
        blacklist = get_blacklist()
    if value.lower() in blacklist:
        # We raise a generic "user with this name already exists" error so as
        # not to make explicit the presence of a blacklist.
        msg = _("Sorry, an account with this username already exists. "
                "Please enter another one.")
        raise colander.Invalid(node, msg)
Exemple #21
0
    def edit_profile(self):
        request = self.request
        schema = schemas.EditProfileSchema().bind(request=request)
        form = deform.Form(schema)

        try:
            appstruct = form.validate(request.POST.items())
        except deform.ValidationFailure as e:
            return dict(errors=e.error.children)

        username = appstruct['username']
        pwd = appstruct['pwd']
        subscriptions = appstruct['subscriptions']

        if subscriptions:
            # Update the subscriptions table
            subs = json.loads(subscriptions)
            if username == subs['uri']:
                s = Subscriptions.get_by_id(request, subs['id'])
                if s:
                    s.active = subs['active']
                    self.db.add(s)
                    return {}
                else:
                    return dict(
                        errors=[
                            {'subscriptions': _('Non existing subscription')}
                        ],
                        code=404
                    )
            else:
                return dict(
                    errors=[{'username': _('Invalid username')}], code=400
                )

        # Password check
        user = self.User.get_user(request, username, pwd)
        if user:
            request.context = user
            return super(ProfileController, self).edit_profile()
        else:
            return dict(errors=[{'pwd': _('Invalid password')}], code=401)
Exemple #22
0
    def edit_profile(self):
        request = self.request
        schema = schemas.EditProfileSchema().bind(request=request)
        form = deform.Form(schema)

        try:
            appstruct = form.validate(request.POST.items())
        except deform.ValidationFailure as e:
            return dict(errors=e.error.children)

        username = appstruct['username']
        pwd = appstruct['pwd']
        subscriptions = appstruct['subscriptions']

        if subscriptions:
            # Update the subscriptions table
            subs = json.loads(subscriptions)
            if username == subs['uri']:
                s = Subscriptions.get_by_id(request, subs['id'])
                if s:
                    s.active = subs['active']
                    self.db.add(s)
                    return {}
                else:
                    return dict(errors=[{
                        'subscriptions':
                        _('Non existing subscription')
                    }],
                                code=404)
            else:
                return dict(errors=[{
                    'username': _('Invalid username')
                }],
                            code=400)

        # Password check
        user = self.User.get_user(request, username, pwd)
        if user:
            request.context = user
            return super(ProfileController, self).edit_profile()
        else:
            return dict(errors=[{'pwd': _('Invalid password')}], code=401)
Exemple #23
0
    def validator(self, node, value):
        super(LoginSchema, self).validator(node, value)
        request = node.bindings['request']
        registry = request.registry
        settings = registry.settings

        allow_email_auth = asbool(
            settings.get('horus.allow_email_auth', False)
        )
        allow_inactive_login = asbool(
            settings.get('horus.allow_inactive_login', False)
        )
        require_activation = asbool(
            settings.get('horus.require_activation', True)
        )

        user_ctor = registry.getUtility(interfaces.IUserClass)

        username = value.get('username')
        password = value.get('password')

        user = user_ctor.get_by_username(request, username)
        if user is None and allow_email_auth:
            user = user_ctor.get_by_email(request, username)

        if user is None:
            err = colander.Invalid(node)
            err['username'] = _('User does not exist.')
            raise err

        if not user_ctor.validate_user(user, password):
            err = colander.Invalid(node)
            err['password'] = _('Incorrect password. Please try again.')
            raise err

        if not allow_inactive_login and require_activation \
                and not user.is_activated:
            reason = _('Your account is not active. Please check your e-mail.')
            raise colander.Invalid(node, reason)

        value['user'] = user
Exemple #24
0
 def respond(self, result):
     errors = isinstance(result, dict) and result.pop('errors', []) or []
     if len(errors):
         for e in errors:
             if isinstance(e, colander.Invalid):
                 msgs = e.messages()
             else:
                 msgs = [str(e)]
             for m in msgs: FlashMessage(self.request, m, kind='error')
         return self.failure(_('Your submission is invalid. '
                               'Please try again.'))
     else:
         return self.success()
Exemple #25
0
def access_token(request):
    """OAuth2 access token provider"""
    for name in [
        'client_id',
        'client_secret',
        'code',
        'state'
    ]:
        if name not in request.params:
            msg = _('Missing parameter "${name}".', mapping={'name': name})
            raise HTTPBadRequest(msg)

    raise NotImplementedError('OAuth provider not implemented yet.')
Exemple #26
0
    def validator(self, node, value):
        super(LoginSchema, self).validator(node, value)
        request = node.bindings['request']
        registry = request.registry
        settings = registry.settings

        allow_email_auth = asbool(settings.get('horus.allow_email_auth',
                                               False))
        allow_inactive_login = asbool(
            settings.get('horus.allow_inactive_login', False))
        require_activation = asbool(
            settings.get('horus.require_activation', True))

        user_ctor = registry.getUtility(interfaces.IUserClass)

        username = value.get('username')
        password = value.get('password')

        user = user_ctor.get_by_username(request, username)
        if user is None and allow_email_auth:
            user = user_ctor.get_by_email(request, username)

        if user is None:
            err = colander.Invalid(node)
            err['username'] = _('User does not exist.')
            raise err

        if not user_ctor.validate_user(user, password):
            err = colander.Invalid(node)
            err['password'] = _('Incorrect password. Please try again.')
            raise err

        if not allow_inactive_login and require_activation \
                and not user.is_activated:
            reason = _('Your account is not active. Please check your e-mail.')
            raise colander.Invalid(node, reason)

        value['user'] = user
Exemple #27
0
def test_profile_invalid_password():
    """ Make sure our edit_profile call validates the user password
    """
    request = _get_fake_request('john', 'doe')

    with testConfig() as config:
        configure(config)
        with patch('horus.models.UserMixin') as mock_user:
            with patch('horus.lib.FlashMessage') as mock_flash:
                mock_user.get_user = MagicMock(side_effect=_bad_password)
                profile = ProfileController(request)
                profile.User = mock_user
                profile.edit_profile()
                assert mock_flash.called_with(request, _('Invalid password.'), kind='error')
Exemple #28
0
    def disable_user(self):
        request = self.request
        schema = schemas.EditProfileSchema().bind(request=request)
        form = deform.Form(schema)

        try:
            appstruct = form.validate(request.POST.items())
        except deform.ValidationFailure as e:
            return dict(errors=e.error.children)

        username = appstruct['username']
        pwd = appstruct['pwd']

        # Password check
        user = self.User.get_user(request, username, pwd)
        if user:
            # TODO: maybe have an explicit disabled flag in the status
            user.password = self.User.generate_random_password()
            self.db.add(user)
            FlashMessage(self.request, _('Account disabled.'), kind='success')
            return {}
        else:
            return dict(errors=[{'pwd': _('Invalid password')}], code=401)
Exemple #29
0
    def disable_user(self):
        request = self.request
        schema = schemas.EditProfileSchema().bind(request=request)
        form = deform.Form(schema)

        try:
            appstruct = form.validate(request.POST.items())
        except deform.ValidationFailure as e:
            return dict(errors=e.error.children)

        username = appstruct['username']
        pwd = appstruct['pwd']

        # Password check
        user = self.User.get_user(request, username, pwd)
        if user:
            # TODO: maybe have an explicit disabled flag in the status
            user.password = self.User.generate_random_password()
            self.db.add(user)
            FlashMessage(self.request, _('Account disabled.'), kind='success')
            return {}
        else:
            return dict(errors=[{'pwd': _('Invalid password')}], code=401)
Exemple #30
0
    def forgot_password(self):
        """
        Handle submission of the forgot password form.

        Validates that the email is one we know about, and then generates a new
        activation for the associated user, and dispatches a "reset your
        password" email which contains a token and/or link to the reset
        password form.
        """
        schema = schemas.ForgotPasswordSchema().bind(request=self.request)
        form = deform.Form(schema)

        # Nothing to do here for logged-in users
        if self.request.authenticated_userid is not None:
            return httpexceptions.HTTPFound(
                location=self.forgot_password_redirect)

        err, appstruct = validate_form(form, self.request.POST.items())
        if err is not None:
            return err

        # If the validation passes, we assume the user exists.
        #
        # TODO: fix this latent race condition by returning a user object in
        # the appstruct.
        user = User.get_by_email(appstruct['email'])

        # Create a new activation for this user. Any previous activation will
        # get overwritten.
        activation = Activation()
        self.request.db.add(activation)
        user.activation = activation

        # Write the new activation to the database in order to set up the
        # foreign key field and generate the code.
        self.request.db.flush()

        # Send the reset password email
        code = user.activation.code
        link = reset_password_link(self.request, code)
        message = reset_password_email(user, code, link)
        mailer = get_mailer(self.request)
        mailer.send(message)

        self.request.session.flash(_("Please check your email to finish "
                                     "resetting your password."),
                                   "success")

        return httpexceptions.HTTPFound(location=self.reset_password_redirect)
Exemple #31
0
def activation_email(request, user):
    """
    Generate an 'activate your account' email for the specified user.

    :rtype: pyramid_mailer.message.Message
    """
    link = request.route_url('activate', id=user.id, code=user.activation.code)

    emailtext = ("Please validate your email and activate your account by "
                 "visiting: {link}")
    body = emailtext.format(link=link)
    msg = Message(subject=_("Please activate your account"),
                  recipients=[user.email],
                  body=body)
    return msg
Exemple #32
0
 def respond(self, result):
     errors = isinstance(result, dict) and result.pop('errors', []) or []
     if len(errors):
         for e in errors:
             if isinstance(e, colander.Invalid):
                 msgs = e.messages()
             else:
                 msgs = [str(e)]
             for m in msgs:
                 FlashMessage(self.request, m, kind='error')
         return self.failure(
             _('Your submission is invalid. '
               'Please try again.'))
     else:
         return self.success()
Exemple #33
0
def test_disable_invalid_password():
    """ Make sure our disable_user call validates the user password
    """
    request = _get_fake_request('john', 'doe')

    with testConfig() as config:
        configure(config)
        with patch('horus.models.UserMixin') as mock_user:
            with patch('horus.lib.FlashMessage') as mock_flash:
                with patch('h.accounts.schemas.EditProfileSchema') as mock_schema:
                    mock_schema.validator = MagicMock(name='validator')
                    mock_user.get_user = MagicMock(side_effect=_bad_password)
                    profile = ProfileController(request)
                    profile.User = mock_user
                    profile.disable_user()
                    assert mock_flash.called_with(request, _('Invalid password.'), kind='error')
Exemple #34
0
def test_disable_invalid_password():
    """ Make sure our disable_user call validates the user password
    """
    request = _get_fake_request("john", "doe")

    with testConfig() as config:
        configure(config)
        with patch("horus.models.UserMixin") as mock_user:
            with patch("horus.lib.FlashMessage") as mock_flash:
                with patch("h.auth.local.schemas.EditProfileSchema") as mock_schema:
                    mock_schema.validator = MagicMock(name="validator")
                    mock_user.get_user = MagicMock(side_effect=_bad_password)
                    profile = ProfileController(request)
                    profile.User = mock_user
                    profile.disable_user()
                    assert mock_flash.called_with(request, _("Invalid password."), kind="error")
Exemple #35
0
def test_profile_invalid_password():
    """ Make sure our edit_profile call validates the user password
    """
    request = _get_fake_request('john', 'doe')

    with testConfig() as config:
        configure(config)
        with patch('horus.models.UserMixin') as mock_user:
            with patch('horus.lib.FlashMessage') as mock_flash:
                mock_user.get_user = MagicMock(side_effect=_bad_password)
                profile = ProfileController(request)
                profile.User = mock_user
                profile.edit_profile()
                assert mock_flash.called_with(request,
                                              _('Invalid password.'),
                                              kind='error')
Exemple #36
0
class EditProfileSchema(CSRFSchema):
    username = colander.SchemaNode(colander.String())
    pwd = colander.SchemaNode(colander.String(),
                              widget=deform.widget.PasswordWidget(),
                              default='',
                              missing=colander.null)
    email = colander.SchemaNode(colander.String(),
                                default='',
                                missing=colander.null)
    password = colander.SchemaNode(colander.String(),
                                   title=_('Password'),
                                   widget=deform.widget.PasswordWidget(),
                                   default='',
                                   missing=colander.null)
    subscriptions = colander.SchemaNode(colander.String(),
                                        missing=colander.null,
                                        default='')
Exemple #37
0
def test_disable_invalid_password():
    """ Make sure our disable_user call validates the user password
    """
    request = _get_fake_request('john', 'doe')

    with testConfig() as config:
        configure(config)
        with patch('horus.models.UserMixin') as mock_user:
            with patch('horus.lib.FlashMessage') as mock_flash:
                with patch(
                        'h.accounts.schemas.EditProfileSchema') as mock_schema:
                    mock_schema.validator = MagicMock(name='validator')
                    mock_user.get_user = MagicMock(side_effect=_bad_password)
                    profile = ProfileController(request)
                    profile.User = mock_user
                    profile.disable_user()
                    assert mock_flash.called_with(request,
                                                  _('Invalid password.'),
                                                  kind='error')
Exemple #38
0
Fichier : views.py Projet : pamo/h
    def edit_profile(self):
        request = self.request
        schema = schemas.EditProfileSchema().bind(request=request)
        form = deform.Form(schema)

        try:
            appstruct = form.validate(request.POST.items())
        except deform.ValidationFailure as e:
            return dict(errors=e.error.children)

        username = appstruct['username']
        pwd = appstruct['pwd']

        # Password check
        user = self.User.get_user(request, username, pwd)
        if user:
            request.context = user
            return super(ProfileController, self).edit_profile()
        else:
            return dict(errors=[{'pwd': _('Invalid password')}], code=401)
Exemple #39
0
    def register(self):
        """
        Handle submission of the new user registration form.

        Validates the form data, creates a new activation for the user, sends
        the activation mail, and then redirects the user to the index.
        """
        err, appstruct = validate_form(self.form, self.request.POST.items())
        if err is not None:
            return err

        db = get_session(self.request)

        # Create the new user from selected form fields
        props = {k: appstruct[k] for k in ['username', 'email', 'password']}
        user = User(**props)
        db.add(user)

        # Create a new activation for the user
        activation = Activation()
        db.add(activation)
        user.activation = activation

        # Flush the session to ensure that the user can be created and the
        # activation is successfully wired up
        db.flush()

        # Send the activation email
        message = activation_email(self.request, user)
        mailer = get_mailer(self.request)
        mailer.send(message)

        self.request.session.flash(_("Thank you for registering! Please check "
                                     "your e-mail now. You can continue by "
                                     "clicking the activation link we have "
                                     "sent you."),
                                   'success')
        self.request.registry.notify(RegistrationEvent(self.request, user))

        return httpexceptions.HTTPFound(
            location=self.request.route_url('index'))
Exemple #40
0
    def activate(self):
        """Activate a user and set a password given an activation code.

        This view is different from the activation view in horus because it
        does not require the user id to be passed. It trusts the activation
        code and updates the password.
        """
        request = self.request
        Str = self.Str

        schema = schemas.ActivationSchema.bind(request=request)
        form = forms.ActivateForm(schema)
        appstruct = None

        try:
            appstruct = form.validate(request.POST.items())
        except deform.ValidationFailure as e:
            return dict(errors=e.error.children)

        code = appstruct['code']
        activation = models.Activation.get_by_code(request, code)

        user = None
        if activation:
            user = self.User.get_by_activation(request, activation)

        if user is None:
            return dict(errors=[_('This activation code is not valid.')])

        user.password = appstruct['password']
        self.db.delete(activation)
        self.db.add(user)

        FlashMessage(request, Str.reset_password_done, kind='success')

        # XXX: Horus should maybe do this for us
        event = events.RegistrationActivatedEvent(request, user, activation)
        request.registry.notify(event)

        return {}
Exemple #41
0
    def activate(self):
        """Activate a user and set a password given an activation code.

        This view is different from the activation view in horus because it
        does not require the user id to be passed. It trusts the activation
        code and updates the password.
        """
        request = self.request
        Str = self.Str

        schema = schemas.ActivationSchema.bind(request=request)
        form = forms.ActivateForm(schema)
        appstruct = None

        try:
            appstruct = form.validate(request.POST.items())
        except deform.ValidationFailure as e:
            return dict(errors=e.error.children)

        code = appstruct['code']
        activation = models.Activation.get_by_code(request, code)

        user = None
        if activation:
            user = self.User.get_by_activation(request, activation)

        if user is None:
            return dict(errors=[_('This activation code is not valid.')])

        user.password = appstruct['password']
        self.db.delete(activation)
        self.db.add(user)

        FlashMessage(request, Str.reset_password_done, kind='success')

        # XXX: Horus should maybe do this for us
        event = events.RegistrationActivatedEvent(request, user, activation)
        request.registry.notify(event)

        return {}
Exemple #42
0
    def reset_password(self):
        """
        Handle submission of the reset password form.

        This function checks that the activation code (i.e. reset token)
        provided by the form is valid, retrieves the user associated with the
        activation code, and resets their password.
        """
        schema = schemas.ResetPasswordSchema().bind(request=self.request)
        form = deform.Form(schema)

        code = self.request.matchdict.get('code')
        if code is None:
            return httpexceptions.HTTPNotFound()

        activation = Activation.get_by_code(self.request, code)
        if activation is None:
            return httpexceptions.HTTPNotFound()

        user = User.get_by_activation(self.request, activation)
        if user is None:
            return httpexceptions.HTTPNotFound()

        if self.request.method != 'POST':
            return httpexceptions.HTTPMethodNotAllowed()

        err, appstruct = validate_form(form, self.request.POST.items())
        if err is not None:
            return err

        user.password = appstruct['password']
        db = get_session(self.request)
        db.delete(activation)

        self.request.session.flash(_('Your password has been reset!'),
                                   'success')
        self.request.registry.notify(PasswordResetEvent(self.request, user))

        return httpexceptions.HTTPFound(location=self.reset_password_redirect)
Exemple #43
0
    def register(self):
        """
        Handle submission of the new user registration form.

        Validates the form data, creates a new activation for the user, sends
        the activation mail, and then redirects the user to the index.
        """
        err, appstruct = validate_form(self.form, self.request.POST.items())
        if err is not None:
            return err

        # Create the new user from selected form fields
        props = {k: appstruct[k] for k in ['username', 'email', 'password']}
        user = User(**props)
        self.request.db.add(user)

        # Create a new activation for the user
        activation = Activation()
        self.request.db.add(activation)
        user.activation = activation

        # Flush the session to ensure that the user can be created and the
        # activation is successfully wired up
        self.request.db.flush()

        # Send the activation email
        message = activation_email(self.request, user)
        mailer = get_mailer(self.request)
        mailer.send(message)

        self.request.session.flash(_("Thank you for registering! Please check "
                                     "your e-mail now. You can continue by "
                                     "clicking the activation link we have "
                                     "sent you."),
                                   'success')
        self.request.registry.notify(RegistrationEvent(self.request, user))

        return httpexceptions.HTTPFound(
            location=self.request.route_url('index'))
Exemple #44
0
    def activate(self):
        """
        Handle a request for a user activation link.

        Checks if the activation code passed is valid, and (as a safety check)
        that it is an activation for the passed user id. If all is well,
        activate the user and redirect them to the stream.
        """
        code = self.request.matchdict.get('code')
        id_ = self.request.matchdict.get('id')

        if code is None or id_ is None:
            return httpexceptions.HTTPNotFound()

        try:
            id_ = int(id_)
        except ValueError:
            return httpexceptions.HTTPNotFound()

        activation = Activation.get_by_code(self.request, code)
        if activation is None:
            return httpexceptions.HTTPNotFound()

        user = User.get_by_activation(self.request, activation)
        if user is None or user.id != id_:
            return httpexceptions.HTTPNotFound()

        # Activate the user (by deleting the activation)
        db = get_session(self.request)
        db.delete(activation)

        self.request.session.flash(_("Your e-mail address has been verified. "
                                     "Thank you!"),
                                   'success')
        self.request.registry.notify(ActivationEvent(self.request, user))

        return httpexceptions.HTTPFound(
            location=self.request.route_url('index'))
Exemple #45
0
    def reset_password(self):
        """
        Handle submission of the reset password form.

        This function checks that the activation code (i.e. reset token)
        provided by the form is valid, retrieves the user associated with the
        activation code, and resets their password.
        """
        schema = schemas.ResetPasswordSchema().bind(request=self.request)
        form = deform.Form(schema)

        code = self.request.matchdict.get('code')
        if code is None:
            return httpexceptions.HTTPNotFound()

        activation = Activation.get_by_code(code)
        if activation is None:
            return httpexceptions.HTTPNotFound()

        user = User.get_by_activation(activation)
        if user is None:
            return httpexceptions.HTTPNotFound()

        if self.request.method != 'POST':
            return httpexceptions.HTTPMethodNotAllowed()

        err, appstruct = validate_form(form, self.request.POST.items())
        if err is not None:
            return err

        user.password = appstruct['password']
        self.request.db.delete(activation)

        self.request.session.flash(_('Your password has been reset!'),
                                   'success')
        self.request.registry.notify(PasswordResetEvent(self.request, user))

        return httpexceptions.HTTPFound(location=self.reset_password_redirect)
Exemple #46
0
class ProfileSchema(CSRFSchema):
    """
    Validates a user profile form.

    This form is broken into multiple parts, for updating the email address,
    password, and subscriptions, so multiple fields are nullable.
    """

    username = colander.SchemaNode(colander.String())
    pwd = colander.SchemaNode(colander.String(),
                              widget=deform.widget.PasswordWidget(),
                              default='',
                              missing=colander.null)
    email = colander.SchemaNode(colander.String(),
                                validator=colander.All(colander.Email(),
                                                       unique_email),
                                default='',
                                missing=colander.null)
    emailAgain = colander.SchemaNode(
        colander.String(),
        default='',
        missing=colander.null,
    )
    password = colander.SchemaNode(colander.String(),
                                   title=_('Password'),
                                   widget=deform.widget.PasswordWidget(),
                                   default='',
                                   missing=colander.null)
    subscriptions = colander.SchemaNode(colander.String(),
                                        missing=colander.null,
                                        default='')

    def validator(self, node, value):
        super(ProfileSchema, self).validator(node, value)

        # Check that emails match
        matching_emails(node, value)
Exemple #47
0
    def activate(self):
        """
        Handle a request for a user activation link.

        Checks if the activation code passed is valid, and (as a safety check)
        that it is an activation for the passed user id. If all is well,
        activate the user and redirect them to the stream.
        """
        code = self.request.matchdict.get('code')
        id_ = self.request.matchdict.get('id')

        if code is None or id_ is None:
            return httpexceptions.HTTPNotFound()

        try:
            id_ = int(id_)
        except ValueError:
            return httpexceptions.HTTPNotFound()

        activation = Activation.get_by_code(code)
        if activation is None:
            return httpexceptions.HTTPNotFound()

        user = User.get_by_activation(activation)
        if user is None or user.id != id_:
            return httpexceptions.HTTPNotFound()

        # Activate the user (by deleting the activation)
        self.request.db.delete(activation)

        self.request.session.flash(_("Your e-mail address has been verified. "
                                     "Thank you!"),
                                   'success')
        self.request.registry.notify(ActivationEvent(self.request, user))

        return httpexceptions.HTTPFound(
            location=self.request.route_url('index'))
Exemple #48
0
def ajax_form(request, result):
    errors = []

    if isinstance(result, httpexceptions.HTTPRedirection):
        request.response.headers.extend(result.headers)
        result = {'status': 'okay'}
    elif isinstance(result, httpexceptions.HTTPError):
        request.response.status_code = result.code
        result = {'status': 'failure', 'reason': str(result)}
    else:
        errors = result.pop('errors', [])
        if errors:
            request.response.status_code = 400
            result['status'] = 'failure'
            result['reason'] = _('Please check your input.')
        else:
            result['status'] = 'okay'

    for e in errors:
        if isinstance(e, colander.Invalid):
            result.setdefault('errors', {})
            result['errors'].update(e.asdict())

    return result
Exemple #49
0
def reset_password_email(user, reset_code, reset_link):
    """
    Generate a 'reset your password' email for the specified user.

    :rtype: pyramid_mailer.message.Message
    """
    emailtext = ("Hello, {username}!\n\n"
                 "Someone requested resetting your password. If it was "
                 "you, reset your password by using this reset code:\n\n"
                 "{code}\n\n"
                 "Alternatively, you can reset your password by "
                 "clicking on this link:\n\n"
                 "{link}\n\n"
                 "If you don't want to change your password, please "
                 "ignore this email message.\n\n"
                 "Regards,\n"
                 "The Hypothesis Team\n")
    body = emailtext.format(code=reset_code,
                            link=reset_link,
                            username=user.username)
    msg = Message(subject=_("Reset your password"),
                  recipients=[user.email],
                  body=body)
    return msg
Exemple #50
0
def ajax_form(request, result):
    errors = []

    if isinstance(result, httpexceptions.HTTPRedirection):
        request.response.headers.extend(result.headers)
        result = {'status': 'okay'}
    elif isinstance(result, httpexceptions.HTTPError):
        request.response.status_code = result.code
        result = {'status': 'failure', 'reason': str(result)}
    else:
        errors = result.pop('errors', [])
        if errors:
            request.response.status_code = 400
            result['status'] = 'failure'
            result['reason'] = _('Please check your input.')
        else:
            result['status'] = 'okay'

    for e in errors:
        if isinstance(e, colander.Invalid):
            result.setdefault('errors', {})
            result['errors'].update(e.asdict())

    return result
Exemple #51
0
def matching_emails(node, value):
    """Colander validator that ensures email and emailAgain fields match."""
    if value.get("email") != value.get("emailAgain"):
        exc = colander.Invalid(node)
        exc["emailAgain"] = _("The emails must match")
        raise exc
Exemple #52
0
class ActivateSchema(CSRFSchema):
    code = colander.SchemaNode(colander.String(), title="Security Code")
    password = colander.SchemaNode(colander.String(),
                                   title=_('New Password'),
                                   validator=colander.Length(min=2),
                                   widget=deform.widget.PasswordWidget())