예제 #1
0
    def test_existing_trial_user_new_subscription_payment(
        self, mocked_date, user=None
    ):
        if not user:
            user = self._make_user(
                email='*****@*****.**',
                groups=[Group.by_name('enabled'), Group.by_name('trial')],
            )

        mocked_date.today.return_value = date(2013, 12, 30)
        view = IPNView(testing.DummyRequest())
        view.provider = 'jvzoo'
        view.params = AttrDict({
            'email': '*****@*****.**',
            'fullname': u'Föo Bar',
            'trans_type': 'BILL',
            'trans_id': 123,
            'product_id': 1,
        })

        resp = view.ipn()
        self.assertEqual(resp, 'Done.')
        self.assertEqual(user.enabled, True)
        self.assertEqual(user.trial, False)
        self.assertEqual(user.valid_to, date(2014, 1, 30))
        self.assertEqual(user.last_payment, date(2013, 12, 30))

        self.assertEqual(len(user.audit_log_entries), 1)
        self.assertEqual(
            user.audit_log_entries[0].event_type.name, u'UserEnabled')
        self.assertEqual(
            user.audit_log_entries[0].comment,
            u'Enabled by jvzoo, transaction id: 123, type: BILL, note: '
            u'regular until 2014-01-30',
        )
예제 #2
0
    def __init__(self, request):
        self.request = request
        self.schema = SQLAlchemySchemaNode(
            User,
            includes=self.fields,
            overrides={
                'properties': {'includes': ['key', 'value']},
                'email': {'validator': deferred_user_email_validator},
                'billing_email': {
                    'validator': deferred_user_billing_email_validator}
            }
        )

        # we don't like the way ColanderAlchemy renders SA Relationships so
        # we manually inject a suitable SchemaNode for groups
        choices = [(group.id, group.name) for group in Group.get_all()]
        enabled = Group.by_name('enabled')
        choices.remove((enabled.id, enabled.name))
        if not request.user.admin:
            admins = Group.by_name('admins')
            choices.remove((admins.id, admins.name))
        self.schema.add(
            node=colander.SchemaNode(
                colander.Set(),
                name='groups',
                missing=[],
                widget=deform.widget.CheckboxChoiceWidget(values=choices),
                validator=deferred_groups_validator,
            ),
        )
예제 #3
0
    def submit_success(self, appstruct):
        group = Group(
            name=appstruct.get('name'),
            product_id=appstruct.get('product_id'),
            validity=appstruct.get('validity'),
            trial_validity=appstruct.get('trial_validity'),
            addon=appstruct.get('addon'),
            forward_ipn_to_url=appstruct.get('forward_ipn_to_url'),
            users=[
                User.by_id(user_id) for user_id in appstruct.get('users', [])
            ],  # noqa
            upgrade_groups=[
                Group.by_id(group_id)
                for group_id in appstruct.get('upgrade_groups', [])
            ],  # noqa
            properties=[
                GroupProperty(key=prop['key'], value=prop['value'])
                for prop in appstruct.get('properties', [])
            ],
        )

        Session.add(group)
        Session.flush()
        self.request.session.flash(u'Group "{}" added.'.format(group.name))
        return HTTPFound(
            location=self.request.route_path('group_edit', group_id=group.id))
예제 #4
0
    def test_existing_user_cancel_subscription(self, mocked_date):
        user = self._make_user(
            email='*****@*****.**',
            groups=[
                Group.by_name('enabled'),
                Group.by_name('trial'),
                Group.by_name('monthly'),
            ])
        mocked_date.today.return_value = date(2013, 12, 30)

        view = IPNView(testing.DummyRequest())
        view.provider = 'clickbank'
        view.params = AttrDict({
            'email': '*****@*****.**',
            'trans_type': 'RFND',
            'trans_id': 123,
            'product_id': 1,
        })
        resp = view.ipn()
        self.assertEqual(resp, 'Done.')
        self.assertEqual(user.enabled, False)
        self.assertEqual(user.valid_to, date(2013, 12, 30))

        self.assertEqual(len(user.audit_log_entries), 1)
        self.assertEqual(
            user.audit_log_entries[0].event_type.name, u'UserDisabled')
        self.assertEqual(
            user.audit_log_entries[0].comment,
            u'Disabled by clickbank, transaction id: 123, type: RFND, note: '
            u'removed from groups: enabled, trial, monthly',
        )
예제 #5
0
    def test_save_success(self):
        self.request.context = User.by_id(2)

        # add a property that will get updated on save_success()
        self.request.context.set_property(key=u'foo', value=u'var')

        result = self.view.save_success(self.APPSTRUCT)
        self.assertIsInstance(result, HTTPFound)
        self.assertEqual(result.location, '/user/2/')

        user = User.by_id(2)
        self.assertEqual(user.email, '*****@*****.**')
        self.assertTrue(verify('new_secret', user.password))
        self.assertEqual(user.fullname, u'Foö Bar')
        self.assertEqual(user.affiliate, u'Aff')
        self.assertEqual(user.billing_email, '*****@*****.**')
        self.assertEqual(user.valid_to, date(2014, 2, 1))
        self.assertEqual(user.last_payment, date(2014, 1, 1))
        self.assertEqual(user.groups,
                         [Group.by_id(1), Group.by_id(3)
                          ])  # enabled user stays enabled  # noqa
        self.assertEqual(user.get_property('foo'), 'bar')
        self.assertEqual(user.get_property('baz'), 'bam')
        self.assertEqual(user.get_property('empty'), None)
        with self.assertRaises(KeyError):
            user.get_property('bimt')  # removed property

        self.assertEqual(
            self.request.session.pop_flash(),
            [u'User "*****@*****.**" modified.'],
        )
예제 #6
0
 def __call__(self):
     warnings = []
     if not Group.by_name('admins'):
         warnings.append('Group "admins" missing.')
     if not Group.by_name('enabled'):
         warnings.append('Group "enabled" missing.')
     if not Group.by_name('trial'):
         warnings.append('Group "trial" missing.')
     return warnings
예제 #7
0
    def test_present_choices_widget(self):
        from pyramid_bimt.models import Group
        groups = [Group(id=1, name='one'), Group(id=2, name='two')]

        group = mock.Mock(name='test_group', product_id=1)
        group.upgrade_groups = groups
        kw = mock.MagicMock()
        kw.get.return_value.user.product_group = group
        widget = self.widget(None, kw)

        self.assertEqual(widget.values[0], (groups[0].id, groups[0].name))
        self.assertEqual(widget.values[1], (groups[1].id, groups[1].name))
        self.assertEqual(widget.template, 'upgrade_select')
예제 #8
0
    def test_exclude(self):
        add_groups()
        add_users()
        mailing = _make_mailing(
            name='foo',
            groups=[Group.by_name('enabled')],
            exclude_groups=[Group.by_name('admins'),
                            Group.by_name('staff')],
        )
        self.request.context = mailing

        self.assertItemsEqual(
            self.view.recipients,
            [User.by_email('*****@*****.**')],
        )
예제 #9
0
    def test_submit_success(self):
        result = self.view.submit_success(self.APPSTRUCT)
        self.assertIsInstance(result, HTTPFound)
        self.assertEqual(result.location, '/portlet/1/edit/')

        portlet = Portlet.by_id(1)
        self.assertEqual(portlet.name, 'foo')
        self.assertEqual(portlet.groups, [Group.by_id(1)])
        self.assertEqual(portlet.exclude_groups, [Group.by_id(2)])
        self.assertEqual(portlet.position, PortletPositions.below_sidebar.name)
        self.assertEqual(portlet.weight, 10)
        self.assertEqual(portlet.html, u'Foo')

        self.assertEqual(self.request.session.pop_flash(),
                         [u'Portlet "foo" added.'])
예제 #10
0
 def test_existing_regular_user_new_subscription_payment(self):
     """Test for the "ValueError: list.remove(x): x not in list" bug."""
     user = self._make_user(
         email='*****@*****.**',
         groups=[Group.by_name('enabled')],
     )
     self.test_existing_trial_user_new_subscription_payment(user=user)
예제 #11
0
    def submit_success(self, appstruct):
        user = User(
            email=appstruct.get('email'),
            fullname=appstruct.get('fullname'),
            affiliate=appstruct.get('affiliate'),
            billing_email=appstruct.get('billing_email'),
            valid_to=appstruct.get('valid_to'),
            last_payment=appstruct.get('last_payment'),
            groups=[Group.by_id(group_id) for group_id in appstruct.get('groups', [])],  # noqa
            properties=[UserProperty(key=prop.get('key'), value=prop.get('value'))  # noqa
                        for prop in appstruct.get('properties', [])],
        )

        if appstruct.get('password'):  # pragma: no branch
            user.password = encrypt(appstruct['password'])

        Session.add(user)
        Session.flush()
        self.request.registry.notify(
            UserCreated(
                self.request,
                user,
                appstruct.get('password'),
                u'Created manually by {}'.format(self.request.user.email)
            )
        )
        self.request.session.flash(u'User "{}" added.'.format(user.email))
        return HTTPFound(
            location=self.request.route_path('user_view', user_id=user.id))
예제 #12
0
    def test_non_product_group_cant_have_upgrade_groups(self):
        from pyramid_bimt.tests.test_group_model import _make_group
        self.request.context = _make_group(name='test', product_id=None)
        view = self.view(self.request)

        self.assertIn(self.request.context, Group.get_all().all())
        self.assertIsNone(view.schema.get('upgrade_groups'))
예제 #13
0
    def test_submit_success(self):
        result = self.view.submit_success(self.APPSTRUCT)
        self.assertIsInstance(result, HTTPFound)
        self.assertEqual(result.location, '/mailing/1/edit/')

        mailing = Mailing.by_id(1)
        self.assertEqual(mailing.name, 'foo')
        self.assertEqual(mailing.groups, [Group.by_id(1)])
        self.assertEqual(mailing.exclude_groups, [Group.by_id(2)])
        self.assertEqual(mailing.trigger, MailingTriggers.never.name)
        self.assertEqual(mailing.days, 30)
        self.assertEqual(mailing.subject, u'Foö')
        self.assertEqual(mailing.body, u'Bär')

        self.assertEqual(self.request.session.pop_flash(),
                         [u'Mailing "foo" added.'])
예제 #14
0
    def __init__(self, request):
        chosen_assets.need()

        self.request = request
        self.schema = SQLAlchemySchemaNode(Mailing, includes=self.fields)

        # we don't like the way ColanderAlchemy renders SA Relationships so
        # we manually inject a suitable SchemaNode for groups
        choices = [(group.id, group.name) for group in Group.get_all()]
        self.schema.add_before(
            'trigger',
            node=colander.SchemaNode(
                colander.Set(),
                name='groups',
                missing=[],
                widget=deform.widget.CheckboxChoiceWidget(values=choices),
            ),
        )
        self.schema.add_before(
            'trigger',
            node=colander.SchemaNode(
                colander.Set(),
                name='exclude_groups',
                missing=[],
                widget=deform.widget.CheckboxChoiceWidget(values=choices),
            ),
        )
예제 #15
0
    def upgrade_subscription_success(self, appstruct):
        old_group = self.request.user.product_group
        new_group = Group.by_id(
            appstruct['change_subscription']['upgrade_subscription'])

        try:
            receipt = self._change_clickbank_subscription(new_group)
        except ClickbankException as exc:
            comment = (
                u'Your upgrade has not completed successfully. Support team '
                'has been notified and they are looking into the problem.')
            self.request.session.flash(comment)
            self.request.registry.notify(
                UserSubscriptionChangeFailed(self.request,
                                             self.request.user,
                                             comment=comment))
            logger.exception(exc)
            return HTTPFound(location=self.request.path_url)

        self.request.user.groups.remove(old_group)
        self.request.user.groups.append(new_group)
        comment = (u'Your subscription ({}) has been upgraded '
                   'from {} to {}.'.format(receipt, old_group.name,
                                           new_group.name))
        self.request.user.set_property('upgrade_completed', True)
        self.request.session.flash(comment)
        self.request.registry.notify(
            UserSubscriptionChanged(self.request,
                                    self.request.user,
                                    comment=comment))
        return HTTPFound(location=self.request.path_url)
예제 #16
0
    def save_success(self, appstruct):
        group = self.request.context

        group.name = appstruct.get('name')
        group.product_id = appstruct.get('product_id')
        group.validity = appstruct.get('validity')
        group.trial_validity = appstruct.get('trial_validity')
        group.addon = appstruct.get('addon')
        group.forward_ipn_to_url = appstruct.get('forward_ipn_to_url')

        group.users = [
            User.by_id(user_id) for user_id in appstruct.get('users', [])
        ]  # noqa
        group.upgrade_groups = [
            Group.by_id(group_id)
            for group_id in appstruct.get('upgrade_groups', [])
        ]  # noqa

        # remove properties that are not present in appstruct
        for prop in copy.copy(group.properties):
            if prop.key not in [p['key'] for p in appstruct['properties']]:
                group.properties.remove(prop)

        # update/create properties present in appstruct
        for prop in appstruct['properties']:
            if group.get_property(prop['key'], None) is not None:
                group.set_property(key=prop['key'], value=prop['value'])
            else:
                group.properties.append(
                    GroupProperty(key=prop['key'], value=prop['value']))

        self.request.session.flash(u'Group "{}" modified.'.format(group.name))
        return HTTPFound(
            location=self.request.route_path('group_edit', group_id=group.id))
예제 #17
0
    def setUp(self):
        self.config = testing.setUp()
        initTestingDB(groups=True)
        Group.by_id(1).product_id = 'old_id'
        Session.flush()

        self.request = testing.DummyRequest()
예제 #18
0
def add_users():
    """Init the '*****@*****.**' and '*****@*****.**' user accounts."""
    with transaction.manager:
        admins = Group.by_name('admins')
        staff = Group.by_name('staff')
        enabled = Group.by_name('enabled')
        trial = Group.by_name('trial')

        # Create the admin user account
        admin = User(
            email=u'*****@*****.**',
            password=SECRET_ENC,
            fullname=u'Ädmin',
            properties=[
                UserProperty(key=u'bimt', value=u'on'),
            ],
        )
        admin.groups.append(admins)
        admin.groups.append(enabled)
        Session.add(admin)

        # Create the staff member account
        staff_member = User(
            email=u'*****@*****.**',
            password=SECRET_ENC,
            fullname=u'Stäff Member',
            properties=[
                UserProperty(key=u'bimt', value=u'on'),
            ],
        )
        staff_member.groups.append(enabled)
        staff_member.groups.append(staff)
        Session.add(staff_member)

        # Create the normal user account
        one = User(
            email=u'*****@*****.**',
            billing_email=u'*****@*****.**',
            password=SECRET_ENC,
            fullname=u'Öne Bar',
            properties=[
                UserProperty(key=u'bimt', value=u'on'),
            ],
        )
        one.groups.append(enabled)
        one.groups.append(trial)
        Session.add(one)
예제 #19
0
 def __getitem__(self, key):
     group = Group.by_id(key)
     if group:
         group.__parent__ = self
         group.__name__ = key
         return group
     else:
         raise KeyError
예제 #20
0
    def test_save_success(self):
        self.request.context = Mailing.by_id(1)

        result = self.view.save_success(self.APPSTRUCT)
        self.assertIsInstance(result, HTTPFound)
        self.assertEqual(result.location, '/mailing/1/edit/')

        mailing = Mailing.by_id(1)
        self.assertEqual(mailing.name, 'bar')
        self.assertEqual(mailing.groups, [Group.by_id(1), Group.by_id(2)])
        self.assertEqual(mailing.exclude_groups, [Group.by_id(3)])
        self.assertEqual(mailing.trigger, MailingTriggers.after_created.name)
        self.assertEqual(mailing.days, 7)
        self.assertEqual(mailing.subject, u'Bär')
        self.assertEqual(mailing.body, u'Bän')
        self.assertEqual(self.request.session.pop_flash(),
                         [u'Mailing "bar" modified.'])
예제 #21
0
def _make_group(
    id=1,
    name='foo',
):
    return Group(
        id=id,
        name=name,
    )
예제 #22
0
    def test_group_cant_be_upgrade_group_to_itself(self):
        from pyramid_bimt.tests.test_group_model import _make_group
        self.request.context = _make_group(name='test1', product_id=1)
        view = self.view(self.request)

        self.assertIn(self.request.context, Group.get_all().all())
        self.assertNotIn((str(
            (self.request.context.id)), self.request.context.name),
                         view.schema.get('upgrade_groups').widget.values)
예제 #23
0
    def test_use_billing_email(self, ClickbankAPI):
        self.request.registry.settings['bimt.clickbank_dev_key'] = 'dev'
        self.request.registry.settings['bimt.clickbank_api_key'] = 'key'
        self.request.user.product_group.product_id = 'foo'

        self.request.user.email = '*****@*****.**'
        self.request.user.billing_email = None
        self.view._change_clickbank_subscription(
            Group(id=1, name='bar', product_id='baz'))
        ClickbankAPI.return_value.change_user_subscription.assert_called_with(
            '*****@*****.**', 'foo', 'baz')

        self.request.user.email = '*****@*****.**'
        self.request.user.billing_email = '*****@*****.**'
        self.view._change_clickbank_subscription(
            Group(id=1, name='bar', product_id='baz'))
        ClickbankAPI.return_value.change_user_subscription.assert_called_with(
            '*****@*****.**', 'foo', 'baz')
예제 #24
0
    def test_save_success(self):
        self.request.context = Portlet.by_id(1)

        result = self.view.save_success(self.APPSTRUCT)
        self.assertIsInstance(result, HTTPFound)
        self.assertEqual(result.location, '/portlet/1/edit/')

        portlet = Portlet.by_id(1)
        self.assertEqual(portlet.name, 'bar')
        self.assertEqual(portlet.groups, [Group.by_id(2), Group.by_id(3)])
        self.assertEqual(portlet.exclude_groups, [
            Group.by_id(4),
        ])
        self.assertEqual(portlet.position, PortletPositions.above_content.name)
        self.assertEqual(portlet.weight, -10)
        self.assertEqual(portlet.html, u'Bar')
        self.assertEqual(self.request.session.pop_flash(),
                         [u'Portlet "bar" modified.'])
예제 #25
0
    def save_success(self, appstruct):
        portlet = self.request.context

        portlet.name = appstruct['name']
        portlet.groups = [
            Group.by_id(group_id) for group_id in appstruct['groups']
        ]  # noqa
        portlet.exclude_groups = [
            Group.by_id(group_id) for group_id in appstruct['exclude_groups']
        ]  # noqa
        portlet.position = appstruct['position']
        portlet.weight = appstruct['weight']
        portlet.html = appstruct['html']

        self.request.session.flash(u'Portlet "{}" modified.'.format(
            portlet.name))
        return HTTPFound(location=self.request.route_path(
            'portlet_edit', portlet_id=portlet.id))
예제 #26
0
def _make_ipn_group():
    group = Group(
        name='monthly',
        product_id=1,
        validity=31,
        trial_validity=7,
    )
    Session.add(group)
    return group
예제 #27
0
 def test_override_ordered_by(self):
     _make_group(name='foo')
     _make_group(name='bar')
     _make_group(name='baz')
     groups = Group.get_all(order_by='id').all()
     self.assertEqual(len(groups), 3)
     self.assertEqual(groups[0].name, 'foo')
     self.assertEqual(groups[1].name, 'bar')
     self.assertEqual(groups[2].name, 'baz')
예제 #28
0
    def test_non_admin_and_non_admins(self):
        from pyramid_bimt.views.user import deferred_groups_validator
        self.request.user.admin = False
        cstruct = [
            str(Group.by_name('staff').id),
        ]

        validator = deferred_groups_validator(None, {'request': self.request})
        self.assertFalse(validator(None, cstruct))
예제 #29
0
    def ipn(self):
        """The main IPN handler, called by the IPN service."""
        # skip over to-be-ignored products
        if self.params.product_id in self.request.registry.settings.get(
                'bimt.products_to_ignore', '').split(','):
            logger.info('The product is listed on the ignore list: {}'.format(
                self.params.product_id))
            return 'Done.'

        # try to find an existing user with given email
        user = User.by_email(self.params.email)
        if not user:
            user = User.by_billing_email(self.params.email)

        # create a new user if no existing user found
        if not user:
            password = generate()
            user = User(
                email=self.params.email,
                billing_email=self.params.email,
                password=encrypt(password),
                fullname=u'{}'.format(self.params.fullname),
                affiliate=u'{}'.format(self.params.get('affiliate', '')),
            )
            Session.add(user)

            comment = COMMENT.format(
                u'Created',
                self.provider,
                self.params.trans_id,
                self.params.trans_type,
                '',
            )
            logger.info(comment)
            self.request.registry.notify(
                UserCreated(self.request, user, password, comment))

        # find a group that is used for given product
        group = Group.by_product_id(self.params.product_id)
        if not group:
            raise ValueError('Cannot find group with product_id "{}"'.format(
                self.params.product_id))

        # perform IPN transaction actions
        self.ipn_transaction(user, group)

        # send request with same parameters to the URL specified on group
        if group.forward_ipn_to_url:
            requests.post(
                group.forward_ipn_to_url,
                params=self.request.POST,
            )
            logger.info('IPN re-posted to {}.'.format(
                group.forward_ipn_to_url))

        logger.info('IPN done.')
        return 'Done.'
예제 #30
0
 def test_ordered_by_name_by_default(self):
     _make_group(name='foo')
     _make_group(name='bar')
     _make_group(name='baz')
     groups = Group.get_all().all()
     self.assertEqual(len(groups), 3)
     self.assertEqual(groups[0].name, 'bar')
     self.assertEqual(groups[1].name, 'baz')
     self.assertEqual(groups[2].name, 'foo')