Example #1
0
def test_set_new_password(party_account_fixture):
    fixture = party_account_fixture

    system_account = fixture.system_account
    new_password_request = NewPasswordRequest(system_account=system_account)
    Session.add(new_password_request)
    new_password = system_account.password * 2
    account_management_interface = AccountManagementInterface()
    Session.add(account_management_interface)

    # Case: the key is invalid
    invalid_key = 'in va lid key which is also too long and contains spaces'
    account_management_interface.email = system_account.email
    account_management_interface.secret = invalid_key
    account_management_interface.password = new_password
    with expected(KeyException):
        account_management_interface.choose_new_password()

    # Case: the email is invalid
    invalid_email = 'i am not a valid email'
    account_management_interface.email = invalid_email
    account_management_interface.secret = new_password_request.as_secret_key()
    account_management_interface.password = new_password
    with expected(InvalidEmailException):
        account_management_interface.choose_new_password()

    # Case: the key is valid
    account_management_interface.email = system_account.email
    account_management_interface.secret = new_password_request.as_secret_key()
    account_management_interface.password = new_password
    account_management_interface.choose_new_password()
    system_account.authenticate(new_password)  # Should not raise exception
Example #2
0
def test_boolean_validation(fixture):

    obj = EmptyStub()
    field = BooleanField()
    field.bind('boolean_attribute', obj)

    # Case: invalid
    invalid_boolean_name = ['negative', 'affirmative', '+', '-', None]
    for boolean_candidate in invalid_boolean_name:
        with expected(AllowedValuesConstraint):
            field.set_user_input(boolean_candidate)
        assert field.validation_error is field.get_validation_constraint_named(
            'pattern')

        # Case: valid
    field.from_input('on')
    assert obj.boolean_attribute is True
    assert field.as_input() == 'on'
    field.from_input('off')
    assert obj.boolean_attribute is False
    assert field.as_input() == 'off'

    # Case: required means True for BooleanField
    field = BooleanField(required=True)
    field.bind('boolean_attribute', obj)
    with expected(AllowedValuesConstraint):
        field.set_user_input('off')
    assert field.validation_error is field.get_validation_constraint_named(
        'pattern')
    with expected(NoException):
        field.from_input('on')
Example #3
0
def test_arguments_to_event(fixture):
    """Only Action objects can be sent as action= when creating an Event. The arguments passed to readable and writable
       should be callable objects with correct signature."""

    # action=
    with expected(IsInstance):
        Event(action=EmptyStub())

    def check_exc(expected_message, ex):
        message = str(ex).split(':')[1][1:]
        assert message.startswith(expected_message)

        # readable/writable are callable

    with expected(IsCallable,
                  test=functools.partial(
                      check_exc, 'readable should be a callable object')):
        Event(readable=EmptyStub())
    with expected(IsCallable,
                  test=functools.partial(
                      check_exc, 'writable should be a callable object')):
        Event(writable=EmptyStub())

    # readable/writable have correct signature
    def do_nothing(a, b, c, d):
        pass

    with expected(IncorrectArgumentError):
        Event(readable=do_nothing)
    with expected(IncorrectArgumentError):
        Event(writable=do_nothing)
Example #4
0
def test_request_email_change(reahl_system_fixture, party_account_fixture):
    fixture = party_account_fixture

    system_account = fixture.new_system_account(activated=False)
    mailer_stub = fixture.mailer
    new_email = '*****@*****.**'
    account_management_interface = fixture.new_account_management_interface(
        system_account=system_account)

    # Case where the user account has not been activated
    assert isinstance(system_account.status, AccountNotActivated)
    account_management_interface.new_email = new_email
    with expected(AccountNotActiveException):
        account_management_interface.request_email_change()

    system_account.activate()
    system_account.disable()
    # Case where the user account is disabled for another reason
    assert isinstance(system_account.status, AccountDisabled)
    account_management_interface.new_email = new_email
    with expected(AccountNotActiveException):
        account_management_interface.request_email_change()

    system_account.enable()
    # Case where the user account is active and enabled, but a clashing email name is requested
    other_party = Party()
    clashing_new_email = '*****@*****.**'
    clashing_system_account = fixture.new_system_account(
        party=other_party, email=clashing_new_email, activated=True)

    account_management_interface.new_email = clashing_new_email
    with expected(NotUniqueException):
        account_management_interface.request_email_change()

    # Case where the user account is active and enabled, and a new unique email name is requested
    assert Session.query(ChangeAccountEmail).count() == 0
    account_management_interface.new_email = new_email
    account_management_interface.request_email_change()
    new_email_request = Session.query(ChangeAccountEmail).filter_by(
        system_account=system_account).one().verify_email_request

    assert mailer_stub.mail_recipients == [new_email]
    assert mailer_stub.mail_sender == reahl_system_fixture.config.accounts.admin_email
    substitutions = {
        'email': new_email,
        'secret_key': new_email_request.as_secret_key()
    }
    expected_subject = Template(
        reahl_system_fixture.config.accounts.email_change_subject).substitute(
            substitutions)
    assert mailer_stub.mail_subject == expected_subject
    expected_message = Template(
        reahl_system_fixture.config.accounts.email_change_email).substitute(
            substitutions)
    assert mailer_stub.mail_message == expected_message

    # Case where a email name is requested which matches an already pending one
    account_management_interface.new_email = new_email
    with expected(NotUniqueException):
        account_management_interface.request_email_change()
Example #5
0
def test_verify_email_change(party_account_fixture):
    fixture = party_account_fixture

    system_account = fixture.system_account
    new_email = '*****@*****.**'
    change_email_action = ChangeAccountEmail(system_account, new_email)
    Session.add(change_email_action)
    request = change_email_action.verify_email_request
    account_management_interface = fixture.account_management_interface

    # Case where there is a password mismatch
    account_management_interface.email = new_email
    account_management_interface.password = '******'
    account_management_interface.secret = request.as_secret_key()
    with expected(InvalidPasswordException, test=assert_is_set_to_commit):
        account_management_interface.verify_email()
    assert system_account.email != new_email

    # Case where there is a key mismatch
    account_management_interface.email = new_email
    account_management_interface.password = system_account.password
    account_management_interface.secret = 'invalid key'
    with expected(KeyException):
        account_management_interface.verify_email()
    assert system_account.email != new_email

    # Case where it works
    assert system_account.email != new_email
    account_management_interface.email = new_email
    account_management_interface.password = system_account.password
    account_management_interface.secret = request.as_secret_key()
    account_management_interface.verify_email()
    assert Session.query(VerifyEmailRequest).filter_by(
        id=request.id).count() == 0
    assert system_account.email == new_email
Example #6
0
def test_reahl_additions():
    ExecutionContext().install()

    try:
        metadata.bind = 'sqlite:///:memory:'
        metadata.create_all()

        address = Address()
        Session.add(address)
        email_field = address.fields.email_address

        # While a programmer would not usually write code like this,
        # it is useful to show how the framework can use Fields and Events
        # to obtain more information about a certain Field/Event:
        assert email_field.label == 'Email'

        # Fields are used (amongst other things) to validate user input:
        with expected(Exception):
            email_field.from_input('invalid email address')

        with expected(NoException):
            assert address.email_address == None
            email_field.from_input('*****@*****.**')
            assert address.email_address == '*****@*****.**'

        # After input was given, the field is set on the object it belongs to:
        # (The value set is a marshalled version of the user input. In this case it is just
        #  a string again, but it could have been, for example an EmailAddress object,
        #  and Integer, or a Date.)
        assert address.email_address == '*****@*****.**'

    finally:
        metadata.bind = None
Example #7
0
def test_file_validation(fixture):
    """A FileField needs to check that the right number of files were submitted, depending on the
       setting of allow_multiple and/or required.
    """

    field = FileField()
    obj = fixture.model_object
    field.bind('file_value', obj)

    files = [EmptyStub(), EmptyStub()]

    # Single file only
    with expected(SingleFileConstraint):
        field.set_user_input(files)

    with expected(NoException):
        field.set_user_input(files[:1])

    # Single file that is required
    field = FileField(required=True)
    field.bind('file_value', obj)

    with expected(NoException):
        field.set_user_input(files[:1])

    with expected(RequiredConstraint):
        field.set_user_input([])

    # Multiple files
    field = FileField(allow_multiple=True)
    field.bind('file_value', obj)

    with expected(NoException):
        field.set_user_input(files)
Example #8
0
def test_date_validation(fixture):
    """A DateField can validate its input based on a min or max value and expects fuzzy but sensible input."""

    field = DateField()
    obj = fixture.model_object

    field.bind('date_value', obj)

    # Case invalid
    with expected(DateConstraint):
        field.set_user_input('sdfdf')

    # Case valid
    with expected(NoException):
        field.set_user_input('13 Dec')

    limit_date = datetime.date(2012, 11, 13)
    before_limit = '12 Nov 2012'
    after_limit = '14 Nov 2012'

    # Case Max
    field = DateField(max_value=limit_date)
    with expected(MaxValueConstraint):
        field.set_user_input(after_limit)

    # Case Min
    field = DateField(min_value=limit_date)
    with expected(MinValueConstraint):
        field.set_user_input(before_limit)
Example #9
0
def test_argument_checks_with_deprecated_methods():
    """When used with @deprecated, argument checks still work."""
    @deprecated('this test class is deprecated', '1.2')
    class ADeprecatedClass:
        @arg_checks(y=IsInstance(int), title=IsInstance(str))
        def __init__(self, x, y, title='a title', style=None):
            pass

    with expected(IsInstance):
        ADeprecatedClass(1, 'y')
    with expected(IsInstance):
        ArgumentCheckedCallable(ADeprecatedClass).checkargs('x', 'y')
    with expected(IncorrectArgumentError):
        ArgumentCheckedCallable(ADeprecatedClass, explanation='an explanation').checkargs('x', NotYetAvailable('x'), title='a valid title')


    class ADeprecatedClass:
        @deprecated('this instance method is deprecated', '1.3')
        @arg_checks(y=IsInstance(int), title=IsInstance(str))
        def instance_method(self, x, y, title='a title', style=None):
            pass

        @deprecated('this class method is deprecated', '2.3')
        @arg_checks(y=IsInstance(int), title=IsInstance(str))
        @classmethod
        def class_method(cls, x, y, title='a title', style=None):
            pass

    with expected(IsInstance):
        ADeprecatedClass().instance_method('x', 'y')
    with expected(IsInstance):
        ADeprecatedClass.class_method('x', 'y')
Example #10
0
def wrong_args_to_input(fixture):
    """Passing the wrong arguments upon constructing an Input results in an error."""

    with expected(IsInstance):
        PrimitiveInput(fixture.form, EmptyStub())

    with expected(IsInstance):
        PrimitiveInput(EmptyStub(), Field())
Example #11
0
def test_event_security_action_and_rw():
    """Supply either an action or a readable/writable to an Event, but not both."""
    def do_nothing():
        pass

    with expected(ProgrammerError):
        Event(action=Action(do_nothing), readable=Action(do_nothing))
    with expected(ProgrammerError):
        Event(action=Action(do_nothing), writable=Action(do_nothing))
Example #12
0
def test_validation(mailer_fixture):
    fixture = mailer_fixture
    with expected(InvalidEmailAddressException):
        MailMessage(fixture.invalid_email_addresses[0],
                    fixture.valid_email_addresses, 'Hi', 'Some Message')

    with expected(InvalidEmailAddressException):
        MailMessage(fixture.valid_email_addresses[0],
                    fixture.invalid_email_addresses, 'Hi', 'Some Message')
Example #13
0
def test_wrong_args_to_input(simple_input_fixture):
    """Passing the wrong arguments upon constructing an Input results in an error."""

    fixture = simple_input_fixture

    with expected(IsInstance):
        PrimitiveInput(fixture.form, EmptyStub(in_namespace=lambda self: self))

    with expected(IsInstance):
        PrimitiveInput(EmptyStub(channel_name='test'), Field())
Example #14
0
def allowed_string_options(fixture):
    """The value of an HTMLAttributeValueOption is constrained to one of its stated valid options if it is set."""
    with expected(NoException):
        HTMLAttributeValueOption('validoption', True, constrain_value_to=['anoption', 'anotheroption', 'validoption'])

    with expected(NoException):
        HTMLAttributeValueOption('invalidoption', False, constrain_value_to=['anoption', 'anotheroption', 'validoption'])

    with expected(ProgrammerError):
        HTMLAttributeValueOption('invalidoption', True, constrain_value_to=['anoption', 'anotheroption', 'validoption'])
Example #15
0
    def widget_adding_error(self, fixture):
        """Passing anything other than other Widgets to .add_child or add_children results in an error."""

        widget = Widget(fixture.view)

        with expected(IsInstance):
            widget.add_child(EmptyStub())

        with expected(IsInstance):
            widget.add_children([Widget(fixture.view), EmptyStub()])
Example #16
0
    def equal_to_constraint(self, fixture):
        other_field = Field(label='other')
        equal_to_constraint = EqualToConstraint(other_field, '$label, $other_label')
        other_field.set_user_input('should be equal to this string', ignore_validation=True)

        #case: valid input
        with expected(NoException):
            equal_to_constraint.validate_parsed_value('should be equal to this string' )

        #case: invalid input
        with expected(EqualToConstraint):
            equal_to_constraint.validate_parsed_value('this is not equal')
Example #17
0
def widget_layout_errors(fixture):
    """A Layout can only be used with a single Widget, and a Widget can only have a single Layout."""

    widget_with_layout = Div(fixture.view).use_layout(Layout())

    with expected(ProgrammerError):
        widget_with_layout.use_layout(Layout())

    re_used_layout = Layout()
    widget_with_reused_layout = Div(fixture.view).use_layout(re_used_layout)
    with expected(ProgrammerError):
        Div(fixture.view).use_layout(re_used_layout)
Example #18
0
    def choice_validation(self, fixture):
        """Input for a ChoiceField is valid only if it matches one of its Choices."""
        field = fixture.field

        # Case invalid
        with expected(fixture.expected_validation_constraint):
            field.set_user_input('sdfdf')

        # Case valid
        for i in fixture.valid_inputs:
            with expected(NoException):
                field.set_user_input(i)
Example #19
0
    def greater_than_constraint(self, fixture):
        other_field = IntegerField(label='other')
        greater_than_constraint = GreaterThanConstraint(other_field, '$label, $other_label')
        other_field.set_user_input('5', ignore_validation=True)

        #case: valid input
        with expected(NoException):
            greater_than_constraint.validate_parsed_value( 6 )

        #case: invalid input
        with expected(GreaterThanConstraint):
            greater_than_constraint.validate_parsed_value( 5 )
Example #20
0
def test_smaller_than_constraint(fixture):

    other_field = IntegerField(label='other')
    smaller_than_constraint = SmallerThanConstraint(other_field, '$label, $other_label')
    other_field.set_user_input('5', ignore_validation=True)

    #case: valid input
    with expected(NoException):
        smaller_than_constraint.validate_parsed_value( 4 )

    #case: invalid input
    with expected(SmallerThanConstraint):
        smaller_than_constraint.validate_parsed_value( 5 )
Example #21
0
def test_stubbable_is_instance():
    """Classes can be marked with a flag to let them pass the IsInstance or IsSubclass checks even
       though they do not inherit from the specified class."""
    class A(object):
        pass

    class B(object):
        is_A = True

    with expected(NoException):
        assert IsInstance(A).is_valid(B())
    with expected(NoException):
        assert IsSubclass(A).is_valid(B)
Example #22
0
def test_logging_in(reahl_system_fixture, party_account_fixture):
    fixture = party_account_fixture

    system_account = fixture.system_account
    login_session = LoginSession.for_session(
        reahl_system_fixture.context.session)
    account_management_interface = fixture.account_management_interface
    account_management_interface.stay_logged_in = False

    # Case: successful email attempt
    assert login_session.account is not system_account
    account_management_interface.log_in()
    assert login_session.account is system_account

    # Case: failed email attempts disable the account
    login_session.account = None
    assert system_account.account_enabled

    account_management_interface.email = system_account.email
    account_management_interface.password = '******'
    for i in list(range(3)):
        with expected(InvalidPasswordException, test=assert_is_set_to_commit):
            account_management_interface.log_in()
        assert system_account.failed_logins == i + 1

    assert login_session.account is None
    assert not system_account.account_enabled

    # Case: Account is locked
    system_account.disable()
    assert isinstance(system_account.status, AccountDisabled)
    with expected(AccountNotActiveException):
        account_management_interface.log_in()
    assert login_session.account is None

    # Case: Account is not activated yet
    login_session.account = None
    system_account = fixture.new_system_account(email='*****@*****.**',
                                                activated=False)

    assert isinstance(system_account.status, AccountNotActivated)
    with expected(AccountNotActiveException):
        account_management_interface.log_in()
    assert login_session.account is None

    # Case: Login for nonexistant email name
    account_management_interface.email = 'i@do not exist'
    account_management_interface.password = '******'
    with expected(InvalidPasswordException, test=assert_not_set_to_commit):
        account_management_interface.log_in()
    assert login_session.account is None
Example #23
0
    def logging_in(self, fixture):
        system_account = fixture.system_account
        login_session = LoginSession.for_session(fixture.context.session)
        account_management_interface = fixture.account_management_interface
        account_management_interface.stay_logged_in = False

        # Case: successful email attempt
        vassert(login_session.account is not system_account)
        account_management_interface.log_in()
        vassert(login_session.account is system_account)

        # Case: failed email attempts disable the account
        login_session.account = None
        vassert(system_account.account_enabled)

        account_management_interface.email = system_account.email
        account_management_interface.password = '******'
        for i in list(range(3)):
            with expected(InvalidPasswordException,
                          test=lambda e: vassert(e.commit)):
                account_management_interface.log_in()
            vassert(system_account.failed_logins == i + 1)

        vassert(login_session.account is None)
        vassert(not system_account.account_enabled)

        # Case: Account is locked
        system_account.disable()
        vassert(isinstance(system_account.status, AccountDisabled))
        with expected(AccountNotActiveException):
            account_management_interface.log_in()
        vassert(login_session.account is None)

        # Case: Account is not activated yet
        login_session.account = None
        system_account = fixture.new_system_account(email='*****@*****.**',
                                                    activated=False)

        vassert(isinstance(system_account.status, AccountNotActivated))
        with expected(AccountNotActiveException):
            account_management_interface.log_in()
        vassert(login_session.account is None)

        # Case: Login for nonexistant email name
        account_management_interface.email = 'i@do not exist'
        account_management_interface.password = '******'
        with expected(InvalidPasswordException,
                      test=lambda e: vassert(not e.commit)):
            account_management_interface.log_in()
        vassert(login_session.account is None)
Example #24
0
    def allowed_values_constraint(self, fixture):
        allowed_values=['a','b']
        allowed_values_constraint = AllowedValuesConstraint(allowed_values=allowed_values)

        #case: valid input
        valid_input = allowed_values[1]
        with expected(NoException):
            allowed_values_constraint.validate_input(valid_input)

        #case: invalid input
        invalid_input = 'ba'
        assert invalid_input not in allowed_values
        with expected(AllowedValuesConstraint):
            allowed_values_constraint.validate_input(invalid_input)
Example #25
0
    def create_account(self, fixture):
        login_email = '*****@*****.**'
        mailer_stub = fixture.mailer
        #        EmailAndPasswordSystemAccount.mailer = mailer_stub
        account_management_interface = fixture.account_management_interface
        account_management_interface.email = login_email

        # Case where the email does not exist as system_account, but as pending new email
        mailer_stub.reset()
        other_system_account = fixture.system_account
        new_email = '*****@*****.**'
        Session.add(ChangeAccountEmail(other_system_account, new_email))

        with expected(NotUniqueException):
            account_management_interface.email = new_email
            account_management_interface.register()

        vassert(not mailer_stub.mail_sent)
        fixture.system_control.rollback()

        # Case where it all works
        vassert(Session.query(ActivateAccount).count() == 0)
        account_management_interface.email = login_email
        system_account = account_management_interface.register()
        [activation_action] = Session.query(ActivateAccount).filter_by(
            system_account=system_account).all()
        activation_request = activation_action.requirements[0]

        vassert(mailer_stub.mail_sent)
        vassert(system_account.email == account_management_interface.email)
        # FIXME: These are those dubious tests where the assert just repeats the implementation verbatim
        vassert(system_account.password_md5 == hashlib.md5(
            account_management_interface.password.encode('utf-8')).hexdigest())
        vassert( system_account.apache_digest == hashlib.md5(('%s:%s:%s' %\
                                              (account_management_interface.email,'',account_management_interface.password)).encode('utf-8')).hexdigest() )
        assert_recent(activation_action.deadline - timedelta(days=10))
        vassert(not system_account.registration_activated)
        vassert(not system_account.account_enabled)
        vassert(not system_account.registration_date)

        vassert(isinstance(system_account, EmailAndPasswordSystemAccount))
        vassert(system_account.owner is None)
        vassert(system_account.id)

        # Case where the email name exists
        mailer_stub.reset()
        with expected(NotUniqueException):
            account_management_interface.register()
        vassert(not mailer_stub.mail_sent)
Example #26
0
    def file_validation_mime_type(self, fixture):
        """A FileField can also limit the mimetype of files allowed to be uploaded.
        """

        field = FileField(allow_multiple=True, accept=['text/*'])
        obj = fixture.model_object
        field.bind('file_value', obj)

        files = [UploadedFile('file1', b'stuff 1', 'text/html'), UploadedFile('file2', b'stuff 2', 'text/xml')]
        with expected(NoException):
            field.set_user_input(files)

        files = [UploadedFile('file1', b'stuff 3', 'text/html'), UploadedFile('file2', b'stuff 4', 'application/java')]
        with expected(MimeTypeConstraint):
            field.set_user_input(files)
Example #27
0
    def password_validation(self, fixture):
        field = PasswordField()
        
        # Case: invalid
        with expected(MinLengthConstraint):
            field.set_user_input('123')
        vassert( field.validation_error is field.get_validation_constraint_named('minlength') )
        with expected(MaxLengthConstraint):
            field.set_user_input('1'*21)
        vassert( field.validation_error is field.get_validation_constraint_named('maxlength') )

        # Case: valid
        with expected(NoException):
            field.set_user_input('my passwôrd')
        vassert( not field.validation_error )
Example #28
0
def test_checking_arguments(argument_check_fixture):
    """Methods can be augmented with argument checks. These checks are done when calling such a method,
       or before an actual call is made using ArgumentCheckedCallable.checkargs."""
    fixture = argument_check_fixture
    with expected(fixture.expected_exception):
        fixture.callable(*fixture.call_args, **fixture.kwargs)
    with expected(fixture.expected_exception):
        ArgumentCheckedCallable(fixture.callable).checkargs(*fixture.args, **fixture.kwargs)

    wrapped_exception = NoException
    if fixture.expected_exception is not NoException:
        wrapped_exception = IncorrectArgumentError

    with expected(wrapped_exception):
        ArgumentCheckedCallable(fixture.callable, explanation='some message').checkargs(*fixture.args, **fixture.kwargs)
Example #29
0
    def file_validation_size(self, fixture):
        """A FileField can also limit the size if files uploaded.
        """

        field = FileField(allow_multiple=True, max_size_bytes=100)
        obj = fixture.model_object
        field.bind('file_value', obj)

        files = [UploadedFile('file1', b'.'*100, ''), UploadedFile('file2', b'.'*50, '')]
        with expected(NoException):
            field.set_user_input(files)

        files = [UploadedFile('file1', b'.'*100, ''), UploadedFile('file2', b'.'*200, '')]
        with expected(FileSizeConstraint):
            field.set_user_input(files)
Example #30
0
    def file_validation_max_files(self, fixture):
        """A maximum can be placed upon the number of files that may be uploaded.
        """

        field = FileField(allow_multiple=True, max_files=1)
        obj = fixture.model_object
        field.bind('file_value', obj)

        files = [UploadedFile('file1', b'stuff 1', '')]
        with expected(NoException):
            field.set_user_input(files)

        files = [UploadedFile('file1', b'stuff 2', ''), UploadedFile('file2', b'stuff 3', '')]
        with expected(MaxFilesConstraint):
            field.set_user_input(files)