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/change user gcp email #689

Merged
merged 5 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
63 changes: 60 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,69 @@ 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
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):
remove_user(old_email)

subscription = user.pro_subscription()
if subscription and not is_email_in_group(email):
add_user(email)

return cls(ok=True)
except Exception as e:
logger.error(e)
return cls(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 +498,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 +509,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
68 changes: 58 additions & 10 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 @@ -110,6 +110,31 @@ 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()
service.members().get(
groupKey=group_key,
memberKey=email,
).execute()
return True
except HttpError as e:
if e.resp.status == 404:
return False
else:
logger.error(f"Erro ao verificar o usuário {email} no grupo {group_key}: {e}")
raise e
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 +148,29 @@ 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)
if account:
remove_user(account.gcp_email or account.email)
else:
remove_user(event.customer.email)


@webhooks.handler("customer.subscription.updated")
Expand All @@ -159,39 +192,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