Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update staging with dev #690

Merged
merged 8 commits into from
Oct 8, 2024
20 changes: 20 additions & 0 deletions backend/apps/account/migrations/0018_account_gcp_email.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 4.2.16 on 2024-09-29 22:44

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("account", "0017_account_available_for_research_and_more"),
]

operations = [
migrations.AddField(
model_name="account",
name="gcp_email",
field=models.EmailField(
blank=True, max_length=254, null=True, verbose_name="GCP email"
),
),
]
1 change: 1 addition & 0 deletions backend/apps/account/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ class Account(BaseModel, AbstractBaseUser, PermissionsMixin):
uuid = models.UUIDField(primary_key=False, default=uuid4)

email = models.EmailField("Email", unique=True)
gcp_email = models.EmailField("GCP email", null=True, blank=True) # Google Cloud Platform email
username = models.CharField("Username", max_length=40, blank=True, null=True, unique=True)

first_name = models.CharField("Nome", max_length=40, blank=True)
Expand Down
2 changes: 1 addition & 1 deletion backend/apps/account/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def create_subscription(user: Account):
customer.subscriber = user
customer.save()
# Add user to Google Group
add_user(user.email)
add_user(user.gcp_email or user.email)


@receiver(post_save, sender=Account)
Expand Down
75 changes: 72 additions & 3 deletions backend/apps/account_payment/graphql.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from stripe import SetupIntent

from backend.apps.account.models import Account, Subscription
from backend.apps.account_payment.webhooks import add_user, remove_user
from backend.apps.account_payment.webhooks import add_user, is_email_in_group, remove_user
from backend.custom.environment import get_backend_url
from backend.custom.graphql_base import CountableConnection, PlainTextNode

Expand Down Expand Up @@ -384,7 +384,7 @@ def mutate(cls, root, info, account_id, subscription_id):

subscription = Subscription.objects.get(id=subscription_id)
assert admin.id == subscription.admin.id
add_user(account.email)
add_user(account.gcp_email or account.email)
subscription.subscribers.add(account)
return cls(ok=True)
except Exception as e:
Expand All @@ -410,14 +410,81 @@ def mutate(cls, root, info, account_id, subscription_id):
account = Account.objects.get(id=account_id)
subscription = Subscription.objects.get(id=subscription_id)
assert admin.id == subscription.admin.id
remove_user(account.email)
remove_user(account.gcp_email or account.email)
subscription.subscribers.remove(account)
return cls(ok=True)
except Exception as e:
logger.error(e)
return cls(errors=[str(e)])


class ChangeUserGCPEmail(Mutation):
"""Change user GCP email"""

ok = Boolean()
errors = List(String)

class Arguments:
email = String(required=True)

@classmethod
@login_required
def mutate(cls, root, info, email):
try:
user = info.context.user
if user is None:
return cls(ok=False, errors=["User is none"])

old_email = user.gcp_email or user.email
if old_email == email:
return cls(ok=True)

user.gcp_email = email
user.save()

if is_email_in_group(old_email):
try:
remove_user(old_email)
except Exception:
pass

subscription = user.pro_subscription

if subscription is None:
return cls(ok=True)

if not is_email_in_group(email):
try:
add_user(email)
except Exception:
pass

return cls(ok=True)
except Exception as e:
logger.error(e)
return cls(ok=False, errors=[str(e)])


# Query to check based on a email if the user is in a group
class IsEmailInGoogleGroup(Mutation):
"""Check if user is in group"""

ok = Boolean()
errors = List(String)

class Arguments:
email = String(required=True)

@classmethod
@login_required
def mutate(cls, root, info, email):
try:
return cls(ok=is_email_in_group(email))
except Exception as e:
logger.error(e)
return cls(errors=[str(e)])


def get_stripe_promo(promotion_code):
"""
Helper function to retrieve a Stripe Promotion Code by its code.
Expand All @@ -443,6 +510,7 @@ def get_stripe_promo(promotion_code):
class Query(ObjectType):
stripe_price = PlainTextNode.Field(StripePriceNode)
all_stripe_price = DjangoFilterConnectionField(StripePriceNode)
is_email_in_google_group = IsEmailInGoogleGroup.Field()


class Mutation(ObjectType):
Expand All @@ -453,6 +521,7 @@ class Mutation(ObjectType):
create_stripe_customer_subscription = StripeSubscriptionCustomerCreateMutation.Field()
update_stripe_customer_subscription = StripeSubscriptionCustomerDeleteMutation.Field()
validate_stripe_coupon = StripeCouponValidationMutation.Field()
change_user_gcp_email = ChangeUserGCPEmail.Field()


# Reference
Expand Down
81 changes: 69 additions & 12 deletions backend/apps/account_payment/webhooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from stripe import Customer as StripeCustomer
from stripe import Subscription as StripeSubscription

from backend.apps.account.models import Subscription
from backend.apps.account.models import Account, Subscription
from backend.custom.client import send_discord_message as send
from backend.custom.environment import get_backend_url

Expand Down Expand Up @@ -87,13 +87,13 @@ def remove_user(email: str, group_key: str = None) -> None:
service = get_service()
service.members().delete(
groupKey=group_key,
memberKey=email,
memberKey=email.lower(),
).execute()
except HttpError as e:
if e.resp.status == 404:
logger.warning(f"{email} já foi removido do google groups")
else:
send(f"Verifique o erro ao remover o usuário do google groups: {e}")
send(f"Verifique o erro ao remover o usuário do google groups '{email}': {e}")
logger.error(e)
raise e

Expand All @@ -110,6 +110,37 @@ def list_user(group_key: str = None):
raise e


def is_email_in_group(email: str, group_key: str = None) -> bool:
"""Check if a user is in a Google group."""
if not group_key:
group_key = settings.GOOGLE_DIRECTORY_GROUP_KEY
if "+" in email and email.index("+") < email.index("@"):
email = email.split("+")[0] + "@" + email.split("@")[1]

try:
service = get_service()
response = (
service.members()
.get(
groupKey=group_key,
memberKey=email.lower(),
)
.execute()
)

member_email = response.get("email")
if not member_email:
return False

return member_email.lower() == email.lower()
except HttpError as e:
logger.error(f"Erro ao verificar o usuário {email} no grupo {group_key}: {e}")
return False
except Exception as e:
logger.error(f"Erro inesperado ao verificar o usuário {email}: {e}")
raise e


@webhooks.handler("customer.updated")
def update_customer(event: Event, **kwargs):
"""Propagate customer email update if exists"""
Expand All @@ -123,21 +154,32 @@ def update_customer(event: Event, **kwargs):
def handle_subscription(event: Event):
"""Handle subscription status"""
subscription = get_subscription(event)
account = Account.objects.filter(email=event.customer.email).first()

if event.data["object"]["status"] in ["trialing", "active"]:
if subscription:
logger.info(f"Adicionando a inscrição do cliente {event.customer.email}")
subscription.is_active = True
subscription.save()

# Add user to google group if subscription exists or not
add_user(event.customer.email)
if account:
add_user(account.gcp_email or account.email)
else:
add_user(event.customer.email)
else:
if subscription:
logger.info(f"Removendo a inscrição do cliente {event.customer.email}")
subscription.is_active = False
subscription.save()
# Remove user from google group if subscription exists or not
remove_user(event.customer.email)
try:
if account:
remove_user(account.gcp_email or account.email)
else:
remove_user(event.customer.email)
except Exception as e:
logger.error(e)


@webhooks.handler("customer.subscription.updated")
Expand All @@ -159,39 +201,54 @@ def unsubscribe(event: Event, **kwargs):
logger.info(f"Removendo a inscrição do cliente {event.customer.email}")
subscription.is_active = False
subscription.save()

account = Account.objects.filter(email=event.customer.email).first()
# Remove user from google group if subscription exists or not
try:
remove_user(event.customer.email)
if account:
remove_user(account.gcp_email or account.email)
else:
remove_user(event.customer.email)
except Exception as e:
logger.error(e)


@webhooks.handler("customer.subscription.paused")
def pause_subscription(event: Event, **kwargs):
"""Pause customer subscription"""
account = Account.objects.filter(email=event.customer.email).first()

if subscription := get_subscription(event):
logger.info(f"Pausando a inscrição do cliente {event.customer.email}")
subscription.is_active = False
subscription.save()

try:
try:
if account:
remove_user(account.gcp_email or account.email)
else:
remove_user(event.customer.email)
except Exception as e:
logger.error(e)
except Exception as e:
logger.error(e)


@webhooks.handler("customer.subscription.resumed")
def resume_subscription(event: Event, **kwargs):
"""Resume customer subscription"""
account = Account.objects.filter(email=event.customer.email).first()

if subscription := get_subscription(event):
logger.info(f"Resumindo a inscrição do cliente {event.customer.email}")
subscription.is_active = True
subscription.save()

try:
try:
if account:
add_user(account.gcp_email or account.email)
else:
add_user(event.customer.email)
except Exception as e:
logger.error(e)
except Exception as e:
logger.error(e)


@webhooks.handler("setup_intent.succeeded")
Expand Down
Loading