Skip to content

Commit

Permalink
fix: #328 Fix sign-up returns validation error on installation withou…
Browse files Browse the repository at this point in the history
…t env variables (#374)
  • Loading branch information
dsowinski2 authored and mkleszcz committed Aug 9, 2023
1 parent 08c28c2 commit 9b65dd9
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
from django.core.management.base import BaseCommand

from config import settings
from ... import models, constants


class Command(BaseCommand):
help = 'Create stripe products and prices required for subscriptions'

def create_or_update_plan(self, plan_config: constants.SubscriptionPlanConfig):
if not settings.STRIPE_LIVE_MODE and not settings.STRIPE_TEST_SECRET_KEY:
return

if settings.STRIPE_LIVE_MODE and not settings.STRIPE_LIVE_SECRET_KEY:
return

product, _ = models.Product.objects.get_or_create_subscription_plan(plan_config=plan_config)
models.Price.objects.get_or_create_subscription_price(product=product, plan_config=plan_config)

Expand Down
14 changes: 13 additions & 1 deletion packages/backend/apps/finances/signals.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import logging

from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver
from stripe.error import AuthenticationError

from .services import subscriptions


logger = logging.getLogger(__name__)

User = get_user_model()


@receiver(post_save, sender=User)
def create_free_plan_subscription(sender, instance, created, **kwargs):
if created:
subscriptions.initialize_user(user=instance)
try:
subscriptions.initialize_user(user=instance)
except AuthenticationError as e:
logger.error(msg=e._message, exc_info=e)
return
except Exception as e:
raise e
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django.core.management.base import BaseCommand

from ...models import User
from apps.finances.services import subscriptions


class Command(BaseCommand):
help = 'Creates stripe customer and schedule subscription plan'

def handle(self, *args, **options):
users = User.objects.filter(djstripe_customers__isnull=True, is_superuser=False)
for user in users:
subscriptions.initialize_user(user=user)
8 changes: 8 additions & 0 deletions packages/backend/apps/users/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.contrib.auth import hashers
from django.contrib.auth.models import Group
from django.core.files.uploadedfile import SimpleUploadedFile, UploadedFile
from djstripe.models import Customer

from common.acl.helpers import CommonGroups

Expand Down Expand Up @@ -91,3 +92,10 @@ def image_factory(name: str, params: Optional[ImageFactoryParams] = None) -> Upl
content=image_field._make_data(params or {}),
content_type=mimetypes.guess_type(name)[0],
)


class StripeCustomerFactory(factory.django.DjangoModelFactory):
class Meta:
model = Customer

subscriber = factory.SubFactory(UserFactory, profile=None)
1 change: 1 addition & 0 deletions packages/backend/apps/users/tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
pytest_factoryboy.register(factories.UserFactory)
pytest_factoryboy.register(factories.UserProfileFactory)
pytest_factoryboy.register(factories.UserAvatarFactory)
pytest_factoryboy.register(factories.StripeCustomerFactory)


@pytest.fixture()
Expand Down
28 changes: 28 additions & 0 deletions packages/backend/apps/users/tests/test_commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import pytest
import factory
from django.db.models import signals

from apps.users.management.commands.init_customers_plans import Command

pytestmark = pytest.mark.django_db


class TestInitCustomerCommand:
@factory.django.mute_signals(signals.post_save)
def test_command_run_for_users_without_customer(self, stripe_customer_factory, user_factory, mocker):
mock = mocker.patch("apps.finances.services.subscriptions.initialize_user")
user = user_factory.create()
stripe_customer_factory.create()

Command().handle()

mock.assert_called_once_with(user=user)

@factory.django.mute_signals(signals.post_save)
def test_command_do_not_run_for_superusers(self, user_factory, mocker):
mock = mocker.patch("apps.finances.services.subscriptions.initialize_user")
user_factory.create(is_superuser=True)

Command().handle()

mock.assert_not_called()
24 changes: 24 additions & 0 deletions packages/backend/apps/users/tests/test_signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import pytest
from stripe.error import AuthenticationError

pytestmark = pytest.mark.django_db


class TestUserPostSaveSignal:
def test_signal_is_not_raising_exception_on_auth_error(self, user_factory, mocker):
mock = mocker.patch("apps.finances.services.subscriptions.initialize_user", side_effect=AuthenticationError())
sentry_mock = mocker.patch("apps.finances.signals.logger.error")

user_factory.create()

mock.assert_called_once()
sentry_mock.assert_called_once()

def test_reraise_stripe_error(self, user_factory, totp_mock, mocker):
initial_error = Exception
mocker.patch("apps.finances.services.subscriptions.initialize_user", side_effect=initial_error())

with pytest.raises(initial_error) as error:
user_factory.create()

assert initial_error == error.type
1 change: 1 addition & 0 deletions packages/backend/scripts/run_local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ if (echo "$STRIPE_LIVE_SECRET_KEY" | grep -q "<CHANGE_ME>") && (echo "$STRIPE_TE
else
python manage.py djstripe_sync_models Product Price
python manage.py init_subscriptions
python manage.py init_customers_plans
echo "Stripe initialized"
fi

Expand Down
1 change: 1 addition & 0 deletions packages/backend/scripts/run_migrations.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@

/bin/chamber exec $CHAMBER_SERVICE_NAME -- ./manage.py migrate
/bin/chamber exec $CHAMBER_SERVICE_NAME -- ./manage.py init_subscriptions
/bin/chamber exec $CHAMBER_SERVICE_NAME -- ./manage.py init_customers_plans
2 changes: 1 addition & 1 deletion packages/backend/sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ sonar.organization=${env.SONAR_ORGANIZATION}
sonar.projectKey=${env.SONAR_BACKEND_PROJECT_KEY}
sonar.python.version=3.11
sonar.python.coverage.reportPaths=cov/coverage.xml
sonar.exclusions=**/migrations/*
sonar.exclusions=**/migrations/*, **/tests/*

0 comments on commit 9b65dd9

Please sign in to comment.