Ejemplo n.º 1
0
    def test_successful_flat_redirect(self):
        # given
        self.client = HelperClient(user=self.new_user)
        self.client.authorise()

        # when
        response = self.client.get(reverse('external_login'),
                                   data={
                                       'redirect': 'https://some-page',
                                       'app_id': 'test'
                                   })

        # then
        self.assertRegex(text=urljoin(response.request['PATH_INFO'],
                                      response.url),
                         expected_regex='https://some-page\?jwt=.*')

        # check jwt
        url_params = response.url.split("?")[1]
        jwt_str = url_params.split("=")[1]
        payload = jwt.decode(jwt_str, verify=False)
        self.assertIsNotNone(payload)
        self.assertEqual(payload['user_slug'], self.new_user.slug)
        self.assertEqual(payload['user_name'], self.new_user.full_name)
        self.assertIsNotNone(payload['exp'])
Ejemplo n.º 2
0
 def test_param_redirect_absent(self):
     self.client = HelperClient(user=self.new_user)
     self.client.authorise()
     response = self.client.get(reverse('external_login'),
                                data={'app_id': 'test'})
     self.assertContains(response=response,
                         text="Нужен параметр ?redirect",
                         status_code=400)
Ejemplo n.º 3
0
    def setUp(self):
        self.client = HelperClient()

        self.existed_user: User = User.objects.create(
            email="*****@*****.**",
            membership_started_at=datetime.now() - timedelta(days=5),
            membership_expires_at=datetime.now() + timedelta(days=5),
            slug="ujlbu4")
Ejemplo n.º 4
0
    def test_user_unauthorized(self):
        # given
        client = HelperClient()
        self.assertFalse(client.is_authorised())

        # when
        response = client.get(reverse('membership_expired'))
        self.assertRedirects(response=response,
                             expected_url=f'/',
                             fetch_redirect_response=False)
Ejemplo n.º 5
0
class ViewExternalLoginTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        # Set up data for the whole TestCase
        cls.new_user: User = User.objects.create(
            email="*****@*****.**",
            membership_started_at=datetime.now() - timedelta(days=5),
            membership_expires_at=datetime.now() + timedelta(days=5),
            slug="ujlbu4"
        )

    def setUp(self):
        self.client = HelperClient()

    def test_successful_flat_redirect(self):
        # given
        self.client = HelperClient(user=self.new_user)
        self.client.authorise()

        # when
        with self.settings(JWT_PRIVATE_KEY=JWT_STUB_VALUES.JWT_PRIVATE_KEY):
            response = self.client.get(reverse('external_login'), data={'redirect': 'some-page'})

        # then
        self.assertRegex(text=urljoin(response.request['PATH_INFO'], response.url),
                         expected_regex='\/auth\/external\/some-page\?jwt=.*')

        # check jwt
        url_params = response.url.split("?")[1]
        jwt_str = url_params.split("=")[1]
        payload = jwt.decode(jwt_str, verify=False)
        self.assertIsNotNone(payload)
        self.assertEqual(payload['user_slug'], self.new_user.slug)
        self.assertEqual(payload['user_name'], self.new_user.full_name)
        self.assertIsNotNone(payload['exp'])

    def test_successful_redirect_with_query_params(self):
        # given
        self.client = HelperClient(user=self.new_user)
        self.client.authorise()

        # when
        with self.settings(JWT_PRIVATE_KEY=JWT_STUB_VALUES.JWT_PRIVATE_KEY):
            response = self.client.get(reverse('external_login'), data={'redirect': 'some-page?param1=value1'})

        # then
        self.assertRegex(text=urljoin(response.request['PATH_INFO'], response.url),
                         expected_regex='\/auth\/external\/some-page\?param1=value1&jwt=.*')

    def test_param_redirect_absent(self):
        response = self.client.get(reverse('external_login'))
        self.assertContains(response=response, text="Нужен параметр ?redirect", status_code=200)

    def test_user_is_unauthorised(self):
        response = self.client.get(reverse('external_login'), data={'redirect': 'some-page'})
        self.assertRedirects(response=response,
                             expected_url='/auth/login/?goto=%2Fauth%2Fexternal%2F%3Fredirect%3Dsome-page',
                             fetch_redirect_response=False)

        self.assertFalse(self.client.is_authorised())
Ejemplo n.º 6
0
 def test_param_wrong_app_id(self):
     self.client = HelperClient(user=self.new_user)
     self.client.authorise()
     response = self.client.get(reverse('external_login'),
                                data={
                                    'app_id': 'UNKNOWN',
                                    'redirect': 'https://some-page'
                                })
     self.assertContains(
         response=response,
         text="Неизвестное приложение, проверьте параметр ?app_id",
         status_code=400)
Ejemplo n.º 7
0
    def test_successful_redirect_with_query_params(self):
        # given
        self.client = HelperClient(user=self.new_user)
        self.client.authorise()

        # when
        with self.settings(JWT_PRIVATE_KEY=JWT_STUB_VALUES.JWT_PRIVATE_KEY):
            response = self.client.get(reverse('external_login'), data={'redirect': 'some-page?param1=value1'})

        # then
        self.assertRegex(text=urljoin(response.request['PATH_INFO'], response.url),
                         expected_regex='\/auth\/external\/some-page\?param1=value1&jwt=.*')
Ejemplo n.º 8
0
    def test_membership_expires_future(self):
        # given
        new_user: User = User.objects.create(
            email="*****@*****.**",
            membership_started_at=datetime.now() - timedelta(days=5),
            membership_expires_at=datetime.now() + timedelta(days=5),
            slug="ujlbu4")
        client = HelperClient(user=new_user)
        client.authorise()

        # when
        response = client.get(reverse('membership_expired'))
        self.assertRedirects(response=response,
                             expected_url=f'/user/{new_user.slug}/',
                             fetch_redirect_response=False)
Ejemplo n.º 9
0
    def test_membership_already_expired(self):
        # given
        new_user: User = User.objects.create(
            email="*****@*****.**",
            membership_started_at=datetime.now() - timedelta(days=10),
            membership_expires_at=datetime.now() - timedelta(days=5),
            slug="ujlbu4")
        client = HelperClient(user=new_user)
        client.authorise()

        # when
        response = client.get(reverse('membership_expired'))
        self.assertContains(response=response,
                            text="Ваша клубная карта истекла",
                            status_code=200)
Ejemplo n.º 10
0
class TestDoneView(TestCase):
    def setUp(self):
        self.client = HelperClient(user=None)

    def test_club_member(self):
        existed_user: User = User.objects.create(
            email="*****@*****.**",
            membership_started_at=datetime.utcnow() - timedelta(days=5),
            membership_expires_at=datetime.utcnow() + timedelta(days=5),
            moderation_status=User.MODERATION_STATUS_APPROVED,
            slug="ujlbu4",
        )
        existed_payment: Payment = Payment.create(
            reference=f"random-reference-{uuid.uuid4()}",
            user=existed_user,
            product=PRODUCTS["club1"])

        response = self.client.get(
            reverse('done'), data={'reference': existed_payment.reference})
        self.assertContains(response=response,
                            text="Ваша клубная карта продлена",
                            status_code=200)

    def test_not_club_member(self):
        existed_user: User = User.objects.create(
            email="*****@*****.**",
            membership_started_at=datetime.utcnow() - timedelta(days=5),
            membership_expires_at=datetime.utcnow() + timedelta(days=5),
            moderation_status=User.MODERATION_STATUS_INTRO,
            slug="ujlbu4",
        )
        existed_payment: Payment = Payment.create(
            reference=f"random-reference-{uuid.uuid4()}",
            user=existed_user,
            product=PRODUCTS["club1"])

        response = self.client.get(
            reverse('done'), data={'reference': existed_payment.reference})
        self.assertContains(response=response,
                            text="Теперь у вас есть аккаунт в Клубе",
                            status_code=200)

    def test_reference_not_found(self):
        response = self.client.get(reverse('done'),
                                   data={'reference': 'wrong-reference'})
        self.assertContains(response=response,
                            text="Теперь у вас есть аккаунт в Клубе",
                            status_code=200)
Ejemplo n.º 11
0
    def test_successful_redirect_with_query_params(self):
        # given
        self.client = HelperClient(user=self.new_user)
        self.client.authorise()

        # when
        response = self.client.get(reverse('external_login'),
                                   data={
                                       'redirect':
                                       'https://some-page?param1=value1',
                                       'app_id': 'test'
                                   })

        # then
        self.assertRegex(
            text=urljoin(response.request['PATH_INFO'], response.url),
            expected_regex='https://some-page\?param1=value1&jwt=.*')
Ejemplo n.º 12
0
    def setUp(self):
        self.client = HelperClient()

        self.stub_patreon_response_oauth_token = {
            "access_token": "xxx-access-token",
            "refresh_token": "xxx-refresh-token",
            "expires_in": (datetime.utcnow() + timedelta(minutes=5)).microsecond,
            "scope": "scope??",
            "token_type": "Bearer"
        }
        self.stub_patreon_response_oauth_identity = None  # doesn't need for now
        self.stub_parse_membership = Membership(
            platform=Platform.patreon,
            user_id=str(uuid.uuid4()),
            full_name="PatreonMember FullName",
            email="*****@*****.**",
            image="http://xxx.url",
            started_at=datetime.utcnow(),
            charged_at=None,
            expires_at=datetime.utcnow() + timedelta(days=100 * 365),
            lifetime_support_cents=400,
            currently_entitled_amount_cents=0
        )
Ejemplo n.º 13
0
class ViewEmailLoginCodeTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        # Set up data for the whole TestCase
        cls.new_user: User = User.objects.create(
            email="*****@*****.**",
            membership_started_at=datetime.now() - timedelta(days=5),
            membership_expires_at=datetime.now() + timedelta(days=5),
            slug="ujlbu4")
        cls.code = Code.create_for_user(user=cls.new_user,
                                        recipient=cls.new_user.email)

    def setUp(self):
        self.client = HelperClient(user=self.new_user)

    def test_correct_code(self):
        # given
        # email is not verified yet
        self.assertFalse(
            User.objects.get(id=self.new_user.id).is_email_verified)

        # when
        response = self.client.get(reverse('email_login_code'),
                                   data={
                                       'email': self.new_user.email,
                                       'code': self.code.code
                                   })

        self.assertRedirects(response=response,
                             expected_url=f'/user/{self.new_user.slug}/',
                             fetch_redirect_response=False)
        self.assertTrue(self.client.is_authorised())
        self.assertTrue(
            User.objects.get(id=self.new_user.id).is_email_verified)

    def test_empty_params(self):
        response = self.client.get(reverse('email_login_code'), data={})
        self.assertRedirects(response=response,
                             expected_url=f'/auth/login/',
                             fetch_redirect_response=False)
        self.assertFalse(self.client.is_authorised())
        self.assertFalse(
            User.objects.get(id=self.new_user.id).is_email_verified)

    def test_wrong_code(self):
        response = self.client.get(reverse('email_login_code'),
                                   data={
                                       'email': self.new_user.email,
                                       'code': 'intentionally-wrong-code'
                                   })

        self.assertEqual(response.status_code,
                         HttpResponseBadRequest.status_code)
        self.assertFalse(self.client.is_authorised())
        self.assertFalse(
            User.objects.get(id=self.new_user.id).is_email_verified)
Ejemplo n.º 14
0
class TestStripeWebhookView(TestCase):
    def setUp(self):
        self.client = HelperClient()

        self.existed_user: User = User.objects.create(
            email="*****@*****.**",
            membership_started_at=datetime.now() - timedelta(days=5),
            membership_expires_at=datetime.now() + timedelta(days=5),
            slug="ujlbu4")

    @staticmethod
    def read_json_event(event_file_name):
        current_dir = os.path.dirname(os.path.abspath(__file__))
        file_path = os.path.join(current_dir,
                                 f'./_stubs/{event_file_name}.json')
        with open(file_path, 'r') as f:
            json_event = yaml.safe_load(f.read())

        return json_event

    def test_event_checkout_session_completed_positive(self):
        # links:
        #   https://stripe.com/docs/webhooks/signatures
        #   https://stripe.com/docs/api/events/object

        # given
        product = PRODUCTS["club1"]
        opened_payment: Payment = Payment.create(
            reference=f"random-reference-{uuid.uuid4()}",
            user=self.existed_user,
            product=product)

        strip_secret = "stripe_secret"
        with self.settings(STRIPE_WEBHOOK_SECRET=strip_secret):
            json_event = self.read_json_event('checkout.session.completed')
            json_event['data']['object']['id'] = opened_payment.reference

            timestamp = int(time.time())
            signed_payload = f"{timestamp}.{json.dumps(json_event)}"
            computed_signature = WebhookSignature._compute_signature(
                signed_payload, strip_secret)

            # when
            header = {
                'HTTP_STRIPE_SIGNATURE':
                f't={timestamp},v1={computed_signature}'
            }
            response = self.client.post(reverse("stripe_webhook"),
                                        data=json_event,
                                        content_type='application/json',
                                        **header)

            # then
            self.assertEqual(response.status_code, 200)
            # subscription prolongated
            user = User.objects.get(id=self.existed_user.id)
            self.assertAlmostEquals(user.membership_expires_at,
                                    self.existed_user.membership_expires_at +
                                    product['data']['timedelta'],
                                    delta=timedelta(seconds=10))

    @skip("do we need throw error in case payment not found?")
    def test_event_checkout_session_completed_negative_payment_not_found(self):
        # given
        strip_secret = "stripe_secret"
        with self.settings(STRIPE_WEBHOOK_SECRET=strip_secret):
            json_event = self.read_json_event('checkout.session.completed')
            json_event['data']['object'][
                'id'] = "some-payment-reference-not-existed"  # not existed payment reference

            timestamp = int(time.time())
            signed_payload = f"{timestamp}.{json.dumps(json_event)}"
            computed_signature = WebhookSignature._compute_signature(
                signed_payload, strip_secret)

            # when
            header = {
                'HTTP_STRIPE_SIGNATURE':
                f't={timestamp},v1={computed_signature}'
            }
            response = self.client.post(reverse("stripe_webhook"),
                                        data=json_event,
                                        content_type='application/json',
                                        **header)

            # then
            self.assertEqual(
                response.status_code,
                409)  # conflict due to payment not found (let it try latter)
            # subscription expiration not prolongated
            user = User.objects.get(id=self.existed_user.id)
            self.assertEqual(user.membership_expires_at,
                             self.existed_user.membership_expires_at)

    def test_event_invoice_paid_with_billing_reason_subscription_create_positive(
            self):
        # links:
        #   https://stripe.com/docs/webhooks/signatures
        #   https://stripe.com/docs/api/events/object

        # given
        strip_secret = "stripe_secret"
        with self.settings(STRIPE_WEBHOOK_SECRET=strip_secret):
            json_event = self.read_json_event('invoice.paid')
            json_event['data']['object']['id'] = f'payment-id-{uuid.uuid4()}'
            json_event['data']['object'][
                'billing_reason'] = "subscription_create"

            timestamp = int(time.time())
            signed_payload = f"{timestamp}.{json.dumps(json_event)}"
            computed_signature = WebhookSignature._compute_signature(
                signed_payload, strip_secret)

            # when
            header = {
                'HTTP_STRIPE_SIGNATURE':
                f't={timestamp},v1={computed_signature}'
            }
            response = self.client.post(reverse("stripe_webhook"),
                                        data=json_event,
                                        content_type='application/json',
                                        **header)

            # then
            self.assertEqual(response.status_code, 200)
            # subscription not prolonging, cause it assumes it has already done in `checkout.session.completed` event
            user = User.objects.get(id=self.existed_user.id)
            self.assertEqual(user.membership_expires_at,
                             self.existed_user.membership_expires_at)

    def test_event_invoice_paid_with_billing_reason_subscription_cycle_positive(
            self):
        # given
        strip_secret = "stripe_secret"
        with self.settings(STRIPE_WEBHOOK_SECRET=strip_secret):
            self.existed_user.stripe_id = f'stripe-id-{uuid.uuid4()}'
            self.existed_user.save()

            json_event = self.read_json_event('invoice.paid')
            json_event['data']['object']['id'] = f'payment-id-{uuid.uuid4()}'
            json_event['data']['object'][
                'billing_reason'] = "subscription_cycle"
            json_event['data']['object'][
                'customer'] = self.existed_user.stripe_id
            product = PRODUCTS['club1_recurrent_yearly']
            json_event['data']['object']['lines']["data"][0]["plan"][
                "id"] = product['stripe_id']

            timestamp = int(time.time())
            signed_payload = f"{timestamp}.{json.dumps(json_event)}"
            computed_signature = WebhookSignature._compute_signature(
                signed_payload, strip_secret)

            # when
            header = {
                'HTTP_STRIPE_SIGNATURE':
                f't={timestamp},v1={computed_signature}'
            }
            response = self.client.post(reverse("stripe_webhook"),
                                        data=json_event,
                                        content_type='application/json',
                                        **header)

            # then
            # subscription prolonged
            self.assertEqual(response.status_code, 200)
            # subscription prolonged
            user = User.objects.get(id=self.existed_user.id)
            self.assertAlmostEquals(user.membership_expires_at,
                                    self.existed_user.membership_expires_at +
                                    product['data']['timedelta'],
                                    delta=timedelta(seconds=10))

    @skip("do we need throw error in case payment not found?")
    def test_event_invoice_paid_negative_user_not_found(self):
        # given
        strip_secret = "stripe_secret"
        with self.settings(STRIPE_WEBHOOK_SECRET=strip_secret):
            strip_secret = "stripe_secret"
            with self.settings(STRIPE_WEBHOOK_SECRET=strip_secret):
                self.existed_user.stripe_id = f'stripe-id-{uuid.uuid4()}'
                self.existed_user.save()

                json_event = self.read_json_event('invoice.paid')
                json_event['data']['object'][
                    'id'] = f'payment-id-{uuid.uuid4()}'
                json_event['data']['object'][
                    'billing_reason'] = "subscription_cycle"
                json_event['data']['object']['customer'] = "not-existed-user"

                timestamp = int(time.time())
                signed_payload = f"{timestamp}.{json.dumps(json_event)}"
                computed_signature = WebhookSignature._compute_signature(
                    signed_payload, strip_secret)

                # when
                header = {
                    'HTTP_STRIPE_SIGNATURE':
                    f't={timestamp},v1={computed_signature}'
                }
                response = self.client.post(reverse("stripe_webhook"),
                                            data=json_event,
                                            content_type='application/json',
                                            **header)

                # then
                self.assertEqual(
                    response.status_code, 409
                )  # conflict due to payment not found (let it try latter)
                # subscription expiration not prolonged
                user = User.objects.get(id=self.existed_user.id)
                self.assertEqual(user.membership_expires_at,
                                 self.existed_user.membership_expires_at)

    def test_event_customer_updated_positive(self):
        strip_secret = "stripe_secret"
        with self.settings(STRIPE_WEBHOOK_SECRET=strip_secret):
            self.assertEqual(self.existed_user.stripe_id, None)

            json_event = self.read_json_event('customer.updated')
            json_event['data']['object']['email'] = self.existed_user.email

            timestamp = int(time.time())
            signed_payload = f"{timestamp}.{json.dumps(json_event)}"
            computed_signature = WebhookSignature._compute_signature(
                signed_payload, strip_secret)

            # when
            header = {
                'HTTP_STRIPE_SIGNATURE':
                f't={timestamp},v1={computed_signature}'
            }
            response = self.client.post(reverse("stripe_webhook"),
                                        data=json_event,
                                        content_type='application/json',
                                        **header)

            # then
            self.assertEqual(response.status_code, 200)
            # subscription not prolonging, cause it assumes it has already done in `checkout.session.completed` event
            user = User.objects.get(id=self.existed_user.id)
            self.assertEqual(user.stripe_id,
                             json_event['data']['object']['id'])
            self.assertEqual(user.membership_expires_at,
                             self.existed_user.membership_expires_at)

    def test_negative_no_payload(self):
        header = {'HTTP_STRIPE_SIGNATURE': 'xxx'}
        response = self.client.post(reverse("stripe_webhook"),
                                    content_type='application/json',
                                    **header)

        self.assertEqual(response.status_code, 400)

    def test_negative_no_signature(self):
        response = self.client.post(reverse("stripe_webhook"),
                                    data={"xxx": 1},
                                    content_type='application/json')

        self.assertEqual(response.status_code, 400)

    def test_negative_invalid_signature(self):
        header = {'HTTP_STRIPE_SIGNATURE': 'invalid-signature'}
        with self.settings(STRIPE_WEBHOOK_SECRET="stripe_secret"):
            response = self.client.post(reverse("stripe_webhook"),
                                        data={"xxx": 1},
                                        content_type='application/json',
                                        **header)

            self.assertEqual(response.status_code, 400)
Ejemplo n.º 15
0
 def setUp(self):
     self.client = HelperClient(user=self.existed_user)
Ejemplo n.º 16
0
class TestPayView(TestCase):
    @classmethod
    def setUpTestData(cls):
        cls.existed_user: User = User.objects.create(
            email="*****@*****.**",
            membership_started_at=datetime.now() - timedelta(days=5),
            membership_expires_at=datetime.now() + timedelta(days=5),
            slug="ujlbu4")

    def setUp(self):
        self.client = HelperClient(user=self.existed_user)

    def test_positive_new_user(self, mocked_stripe):
        # given
        product_code = "club1"
        email = f"new-user-{uuid.uuid4()}@email.com"
        StripeSession = namedtuple('Session', "id")
        session = StripeSession(id=f"{uuid.uuid4()}")
        mocked_stripe.checkout.Session.create.return_value = session

        # when
        response = self.client.get(
            reverse("pay"),
            data={
                "product_code": product_code,
                # "is_recurrent": PRODUCTS[product_code]["recurrent"],
                "email": email
            })

        # check
        self.assertTrue(User.objects.filter(email=email).exists(), )
        created_user: User = User.objects.get(email=email)
        self.assertEqual(created_user.email, email)
        self.assertEqual(created_user.membership_platform_type,
                         User.MEMBERSHIP_PLATFORM_DIRECT)
        self.assertEqual(created_user.full_name,
                         email.replace("@email.com", ""))
        self.assertAlmostEquals(created_user.membership_started_at,
                                datetime.utcnow(),
                                delta=timedelta(seconds=5))
        self.assertAlmostEquals(created_user.membership_expires_at,
                                datetime.utcnow(),
                                delta=timedelta(seconds=5))
        self.assertEqual(created_user.moderation_status,
                         User.MODERATION_STATUS_INTRO)

        self.assertTrue(Payment.get(reference=session.id))
        self.assertContains(response=response,
                            text="Платим 💰",
                            status_code=200)

    def test_positive_existed_authorised_user(self, mocked_stripe):
        # given
        product_code = "club1"
        StripeSession = namedtuple('Session', "id")
        session = StripeSession(id=f"{uuid.uuid4()}")
        mocked_stripe.checkout.Session.create.return_value = session
        self.client.authorise()

        # when
        response = self.client.get(reverse("pay"),
                                   data={
                                       "product_code": product_code,
                                   })

        # check
        self.assertTrue(
            User.objects.filter(email=self.existed_user.email).exists(), )
        user_after: User = User.objects.get(email=self.existed_user.email)
        self.assertEqual(user_after.membership_platform_type,
                         self.existed_user.membership_platform_type)
        self.assertEqual(user_after.full_name, self.existed_user.full_name)
        self.assertEqual(user_after.membership_started_at,
                         self.existed_user.membership_started_at)
        self.assertAlmostEquals(user_after.membership_expires_at,
                                self.existed_user.membership_expires_at)
        self.assertEqual(user_after.moderation_status,
                         self.existed_user.moderation_status)

        self.assertTrue(Payment.get(reference=session.id))
        self.assertContains(response=response,
                            text="Платим 💰",
                            status_code=200)

    def test_negative_new_user_with_broken_email(self, mocked_stripe):
        # given
        product_code = "club1"
        broken_email = f"email-invalid"

        # when
        response = self.client.get(reverse("pay"),
                                   data={
                                       "product_code": product_code,
                                       "email": broken_email
                                   })

        # check
        self.assertFalse(User.objects.filter(email=broken_email).exists(), )
        self.assertContains(response=response,
                            text="Плохой e-mail адрес",
                            status_code=200)

    def test_product_not_found(self, mocked_stripe):
        product_code = "unexisted-product-code"

        # when
        response = self.client.get(reverse("pay"),
                                   data={
                                       "product_code": product_code,
                                   })

        # check
        self.assertContains(response=response,
                            text="Не выбран пакет",
                            status_code=200)
Ejemplo n.º 17
0
 def _authorized_client(user):
     client = HelperClient(user)
     if user is not None:
         client.authorise()
     return client
Ejemplo n.º 18
0
 def setUp(self):
     self.client = HelperClient(user=self.new_user)
Ejemplo n.º 19
0
class ViewExternalLoginTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        # Set up data for the whole TestCase
        cls.new_user: User = User.objects.create(
            email="*****@*****.**",
            membership_started_at=datetime.now() - timedelta(days=5),
            membership_expires_at=datetime.now() + timedelta(days=5),
            slug="ujlbu4")

        cls.app: Apps = Apps.objects.create(
            id="test",
            name="test",
            jwt_secret=JWT_STUB_VALUES.JWT_PRIVATE_KEY,
            jwt_algorithm="RS256",
            jwt_expire_hours=1,
            redirect_urls=["https://some-page"],
        )

    def setUp(self):
        self.client = HelperClient()

    def test_successful_flat_redirect(self):
        # given
        self.client = HelperClient(user=self.new_user)
        self.client.authorise()

        # when
        response = self.client.get(reverse('external_login'),
                                   data={
                                       'redirect': 'https://some-page',
                                       'app_id': 'test'
                                   })

        # then
        self.assertRegex(text=urljoin(response.request['PATH_INFO'],
                                      response.url),
                         expected_regex='https://some-page\?jwt=.*')

        # check jwt
        url_params = response.url.split("?")[1]
        jwt_str = url_params.split("=")[1]
        payload = jwt.decode(jwt_str, verify=False)
        self.assertIsNotNone(payload)
        self.assertEqual(payload['user_slug'], self.new_user.slug)
        self.assertEqual(payload['user_name'], self.new_user.full_name)
        self.assertIsNotNone(payload['exp'])

    def test_successful_redirect_with_query_params(self):
        # given
        self.client = HelperClient(user=self.new_user)
        self.client.authorise()

        # when
        response = self.client.get(reverse('external_login'),
                                   data={
                                       'redirect':
                                       'https://some-page?param1=value1',
                                       'app_id': 'test'
                                   })

        # then
        self.assertRegex(
            text=urljoin(response.request['PATH_INFO'], response.url),
            expected_regex='https://some-page\?param1=value1&jwt=.*')

    def test_param_wrong_app_id(self):
        self.client = HelperClient(user=self.new_user)
        self.client.authorise()
        response = self.client.get(reverse('external_login'),
                                   data={
                                       'app_id': 'UNKNOWN',
                                       'redirect': 'https://some-page'
                                   })
        self.assertContains(
            response=response,
            text="Неизвестное приложение, проверьте параметр ?app_id",
            status_code=400)

    def test_param_redirect_absent(self):
        self.client = HelperClient(user=self.new_user)
        self.client.authorise()
        response = self.client.get(reverse('external_login'),
                                   data={'app_id': 'test'})
        self.assertContains(response=response,
                            text="Нужен параметр ?redirect",
                            status_code=400)

    def test_user_is_unauthorised(self):
        response = self.client.get(reverse('external_login'),
                                   data={
                                       'redirect': 'some-page',
                                       'app_id': 'test'
                                   })
        self.assertRedirects(
            response=response,
            expected_url=
            '/auth/login/?goto=%2Fauth%2Fexternal%2F%3Fredirect%3Dsome-page',
            fetch_redirect_response=False)

        self.assertFalse(self.client.is_authorised())
Ejemplo n.º 20
0
 def setUp(self):
     self.client = HelperClient()
Ejemplo n.º 21
0
class ViewEmailLoginTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        # Set up data for the whole TestCase
        cls.new_user: User = User.objects.create(
            email="*****@*****.**",
            membership_started_at=datetime.now() - timedelta(days=5),
            membership_expires_at=datetime.now() + timedelta(days=5),
            slug="ujlbu4"
        )

        cls.broker = brokers.get_broker()
        cls.assertTrue(cls.broker.ping(), 'broker is not available')

    def setUp(self):
        self.client = HelperClient(user=self.new_user)

        self.broker.purge_queue()

    def test_login_by_email_positive(self):
        # when
        response = self.client.post(reverse('email_login'),
                                    data={'email_or_login': self.new_user.email, })

        # then
        self.assertContains(response=response, text="Вам отправлен код!", status_code=200)
        issued_code = Code.objects.filter(recipient=self.new_user.email).get()
        self.assertIsNotNone(issued_code)

        # check email was sent
        packages = self.broker.dequeue()
        task_signed = packages[0][1]
        task = SignedPackage.loads(task_signed)
        self.assertEqual(task['func'].__name__, 'send_auth_email')
        self.assertEqual(task['args'][0].id, self.new_user.id)
        self.assertEqual(task['args'][1].id, issued_code.id)

        # check notify wast sent
        packages = self.broker.dequeue()
        task_signed = packages[0][1]
        task = SignedPackage.loads(task_signed)
        self.assertEqual(task['func'].__name__, 'notify_user_auth')
        self.assertEqual(task['args'][0].id, self.new_user.id)
        self.assertEqual(task['args'][1].id, issued_code.id)

        # it's not yet authorised, only code was sent
        self.assertFalse(self.client.is_authorised())

    def test_login_user_not_exist(self):
        response = self.client.post(reverse('email_login'),
                                    data={'email_or_login': '******', })
        self.assertContains(response=response, text="Такого юзера нет 🤔", status_code=200)

    def test_secret_hash_login(self):
        response = self.client.post(reverse('email_login'),
                                    data={'email_or_login': self.new_user.secret_auth_code, })

        self.assertRedirects(response=response, expected_url=f'/user/{self.new_user.slug}/',
                             fetch_redirect_response=False)
        self.assertTrue(self.client.is_authorised())

    def test_secret_hash_user_not_exist(self):
        response = self.client.post(reverse('email_login'),
                                    data={'email_or_login': '******', })
        self.assertContains(response=response, text="Такого юзера нет 🤔", status_code=200)

    @skip("todo")
    def test_secret_hash_cancel_user_deletion(self):
        # todo: mark user as deleted
        self.assertTrue(False)

    def test_email_login_missed_input_data(self):
        response = self.client.post(reverse('email_login'), data={})
        self.assertRedirects(response=response, expected_url=f'/auth/login/',
                             fetch_redirect_response=False)

    def test_email_login_wrong_method(self):
        response = self.client.get(reverse('email_login'))
        self.assertRedirects(response=response, expected_url=f'/auth/login/',
                             fetch_redirect_response=False)

        response = self.client.put(reverse('email_login'))
        self.assertRedirects(response=response, expected_url=f'/auth/login/',
                             fetch_redirect_response=False)

        response = self.client.delete(reverse('email_login'))
        self.assertRedirects(response=response, expected_url=f'/auth/login/',
                             fetch_redirect_response=False)
Ejemplo n.º 22
0
class ViewsAuthTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        # Set up data for the whole TestCase
        cls.new_user: User = User.objects.create(
            email="*****@*****.**",
            membership_started_at=datetime.now() - timedelta(days=5),
            membership_expires_at=datetime.now() + timedelta(days=5),
            slug="ujlbu4"
        )

    def setUp(self):
        self.client = HelperClient(user=self.new_user)

    def test_join_anonymous(self):
        response = self.client.get(reverse('join'))
        # check auth/join.html is rendered
        self.assertContains(response=response, text="Всегда рады новым членам", status_code=200)

    def test_join_authorised(self):
        self.client.authorise()

        response = self.client.get(reverse('join'))
        self.assertRedirects(response=response, expected_url=f'/user/{self.new_user.slug}/',
                             fetch_redirect_response=False)

    def test_login_anonymous(self):
        response = self.client.get(reverse('login'))
        # check auth/join.html is rendered
        self.assertContains(response=response, text="Вход по почте или нику", status_code=200)

    def test_login_authorised(self):
        self.client.authorise()

        response = self.client.get(reverse('login'))
        self.assertRedirects(response=response, expected_url=f'/user/{self.new_user.slug}/',
                             fetch_redirect_response=False)

    def test_logout_success(self):
        self.client.authorise()

        response = self.client.post(reverse('logout'))

        self.assertRedirects(response=response, expected_url=f'/', fetch_redirect_response=False)
        self.assertFalse(self.client.is_authorised())

    def test_logout_unauthorised(self):
        response = self.client.post(reverse('logout'))
        self.assertTrue(self.client.is_access_denied(response))

    def test_logout_wrong_method(self):
        self.client.authorise()

        response = self.client.get(reverse('logout'))
        self.assertEqual(response.status_code, HttpResponseNotAllowed.status_code)

        response = self.client.put(reverse('logout'))
        self.assertEqual(response.status_code, HttpResponseNotAllowed.status_code)

        response = self.client.delete(reverse('logout'))
        self.assertEqual(response.status_code, HttpResponseNotAllowed.status_code)

    def test_debug_dev_login_unauthorised(self):
        response = self.client.post(reverse('debug_dev_login'))
        self.assertTrue(self.client.is_authorised())

        me = self.client.print_me()
        self.assertIsNotNone(me['id'])
        self.assertEqual(me['email'], '*****@*****.**')
        self.assertTrue(me['is_email_verified'])
        self.assertTrue(me['slug'], 'dev')
        self.assertEqual(me['moderation_status'], 'approved')
        self.assertEqual(me['roles'], ['god'])
        # todo: check created post (intro)

    def test_debug_dev_login_authorised(self):
        self.client.authorise()

        response = self.client.post(reverse('debug_dev_login'))
        self.assertTrue(self.client.is_authorised())

        me = self.client.print_me()
        self.assertTrue(me['slug'], self.new_user.slug)

    def test_debug_random_login_unauthorised(self):
        response = self.client.post(reverse('debug_random_login'))
        self.assertTrue(self.client.is_authorised())

        me = self.client.print_me()
        self.assertIsNotNone(me['id'])
        self.assertIn('@random.dev', me['email'])
        self.assertTrue(me['is_email_verified'])
        self.assertEqual(me['moderation_status'], 'approved')
        self.assertEqual(me['roles'], [])
Ejemplo n.º 23
0
    def setUp(self):
        self.client = HelperClient(user=self.new_user)

        self.broker.purge_queue()
Ejemplo n.º 24
0
 def setUp(self):
     self.client = HelperClient(user=None)
Ejemplo n.º 25
0
class ViewPatreonOauthCallbackTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        # Set up data for the whole TestCase
        cls.new_user: User = User.objects.create(
            email="*****@*****.**",
            membership_started_at=datetime.now() - timedelta(days=5),
            membership_expires_at=datetime.now() + timedelta(days=5),
            slug="ujlbu4"
        )

    def setUp(self):
        self.client = HelperClient()

        self.stub_patreon_response_oauth_token = {
            "access_token": "xxx-access-token",
            "refresh_token": "xxx-refresh-token",
            "expires_in": (datetime.utcnow() + timedelta(minutes=5)).microsecond,
            "scope": "scope??",
            "token_type": "Bearer"
        }
        self.stub_patreon_response_oauth_identity = None  # doesn't need for now
        self.stub_parse_membership = Membership(
            platform=Platform.patreon,
            user_id=str(uuid.uuid4()),
            full_name="PatreonMember FullName",
            email="*****@*****.**",
            image="http://xxx.url",
            started_at=datetime.utcnow(),
            charged_at=None,
            expires_at=datetime.utcnow() + timedelta(days=100 * 365),
            lifetime_support_cents=400,
            currently_entitled_amount_cents=0
        )

    def test_successful_login_new_member(self, mocked_patreon):
        # given
        mocked_patreon.fetch_auth_data.return_value = self.stub_patreon_response_oauth_token
        mocked_patreon.fetch_user_data.return_value = self.stub_patreon_response_oauth_identity
        membership = self.stub_parse_membership
        membership.user_id = str(uuid.uuid4())
        membership.email = f"{membership.user_id}@email.com"
        mocked_patreon.parse_active_membership.return_value = membership

        # when
        response = self.client.get(reverse('patreon_oauth_callback'), data={'code': '1234'})

        # then
        self.assertRedirects(response=response, expected_url=f'/user/PatreonMemberFullName/',
                             fetch_redirect_response=False)
        self.assertTrue(self.client.is_authorised())
        # created user
        created_user: User = User.objects.filter(email=membership.email).get()
        self.assertIsNotNone(created_user)
        self.assertEqual(created_user.patreon_id, membership.user_id)
        self.assertEqual(created_user.full_name, "PatreonMember FullName")
        self.assertEqual(created_user.membership_platform_type, "patreon")
        self.assertEqual(created_user.membership_started_at, membership.started_at)
        self.assertEqual(created_user.membership_expires_at, membership.expires_at)
        self.assertEqual(created_user.balance, 4)  # 400 / 100
        self.assertFalse(created_user.is_email_verified)
        self.assertEqual(created_user.membership_platform_data, {'access_token': 'xxx-access-token',
                                                                 'refresh_token': 'xxx-refresh-token'})

    def test_successful_login_existed_member(self, mocked_patreon):
        # given
        mocked_patreon.fetch_auth_data.return_value = self.stub_patreon_response_oauth_token
        mocked_patreon.fetch_user_data.return_value = self.stub_patreon_response_oauth_identity
        membership = self.stub_parse_membership
        membership.email = "*****@*****.**"
        membership.lifetime_support_cents = 100500
        mocked_patreon.parse_active_membership.return_value = membership

        # when
        response = self.client.get(reverse('patreon_oauth_callback'), data={'code': '1234'})

        # then
        self.assertRedirects(response=response, expected_url=f'/user/ujlbu4/',
                             fetch_redirect_response=False)
        self.assertTrue(self.client.is_authorised())
        # user updated attributes
        created_user: User = User.objects.filter(email="*****@*****.**").get()
        self.assertIsNotNone(created_user)
        self.assertEqual(created_user.membership_expires_at, membership.expires_at)
        self.assertEqual(created_user.balance, 1005)  # 100500 / 100
        self.assertEqual(created_user.membership_platform_data, {'access_token': 'xxx-access-token',
                                                                 'refresh_token': 'xxx-refresh-token'})

    def test_patreon_exception(self, mocked_patreon):
        # given
        mocked_patreon.fetch_auth_data.side_effect = PatreonException("custom_test_exception")

        # when
        response = self.client.get(reverse('patreon_oauth_callback'), data={'code': '1234'})

        # then
        self.assertContains(response=response, text="Не получилось загрузить ваш профиль с серверов патреона",
                            status_code=200)

    def test_patreon_not_membership(self, mocked_patreon):
        # given
        mocked_patreon.fetch_auth_data.return_value = self.stub_patreon_response_oauth_token
        mocked_patreon.fetch_user_data.return_value = None
        mocked_patreon.parse_active_membership.return_value = None  # no membership

        # when
        response = self.client.get(reverse('patreon_oauth_callback'), data={'code': '1234'})

        # then
        self.assertContains(response=response, text="Надо быть патроном, чтобы состоять в Клубе", status_code=200)

    def test_param_code_absent(self, mocked_patreon=None):
        response = self.client.get(reverse('patreon_oauth_callback'), data={})
        self.assertContains(response=response, text="Что-то сломалось между нами и патреоном", status_code=200)