Skip to content

Commit

Permalink
Add my changes
Browse files Browse the repository at this point in the history
  • Loading branch information
hiroshinishio committed Nov 18, 2024
1 parent 260011b commit 9e78a62
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 144 deletions.
4 changes: 2 additions & 2 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def get_env_var(name: str) -> str:
]
GITHUB_ISSUE_DIR = ".github/ISSUE_TEMPLATE"
GITHUB_ISSUE_TEMPLATES: list[str] = ["bug_report.yml", "feature_request.yml"]
GITHUB_NOREPLY_EMAIL_DOMAIN = "users.noreply.github.com"
GITHUB_NOREPLY_EMAIL_DOMAIN = "users.noreply.github.com" # https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-email-preferences/setting-your-commit-email-address
GITHUB_PRIVATE_KEY_ENCODED: str = get_env_var(name="GH_PRIVATE_KEY")
GITHUB_PRIVATE_KEY: bytes = base64.b64decode(s=GITHUB_PRIVATE_KEY_ENCODED)
GITHUB_WEBHOOK_SECRET: str = get_env_var(name="GH_WEBHOOK_SECRET")
Expand Down Expand Up @@ -103,7 +103,7 @@ def get_env_var(name: str) -> str:
OWNER_NAME = "installation-test"
EXCEPTION_OWNERS = ["gitautoai", "hiroshinishio"]
OWNER_TYPE = "Organization"
TEST_EMAIL = "test@gitauto.ai"
UNIQUE_ISSUE_ID = "O/gitautoai/test#1"
USER_ID = -1
USER_NAME = "username-test"
EMAIL = "test@gitauto.com"
7 changes: 4 additions & 3 deletions services/gitauto_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ async def handle_gitauto(payload: GitHubLabeledPayload, trigger_type: str) -> No
github_urls, other_urls = extract_urls(text=issue_body)
installation_id: int = payload["installation"]["id"]
token: str = get_installation_access_token(installation_id=installation_id)
email: str | None = get_user_public_email(username=sender_name, token=token)
sender_email = get_user_public_email(username=sender_name, token=token)

base_args: BaseArgs = {
"owner": owner_name,
"repo": repo_name,
Expand Down Expand Up @@ -135,9 +135,10 @@ async def handle_gitauto(payload: GitHubLabeledPayload, trigger_type: str) -> No
unique_issue_id = f"{owner_type}/{owner_name}/{repo_name}#{issue_number}"
usage_record_id = supabase_manager.create_user_request(
user_id=sender_id,
user_name=sender_name,
installation_id=installation_id,
unique_issue_id=unique_issue_id,
email=email,
email=sender_email,
)
add_reaction_to_issue(
issue_number=issue_number, content="eyes", base_args=base_args
Expand Down
25 changes: 14 additions & 11 deletions services/github/github_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,21 +240,17 @@ def create_comment_on_issue_with_gitauto_button(payload: GitHubLabeledPayload) -
issue_number: int = payload["issue"]["number"]
user_id: int = payload["sender"]["id"]
user_name: str = payload["sender"]["login"]
email: str | None = get_user_public_email(username=user_name, token=token)
user_email: str | None = get_user_public_email(username=user_name, token=token)

supabase_manager = SupabaseManager(url=SUPABASE_URL, key=SUPABASE_SERVICE_ROLE_KEY)

# Proper issue generation comment, create user if not exist (first issue in an orgnanization)
first_issue = False
if not supabase_manager.user_exists(user_id=user_id):
supabase_manager.create_user(
user_id=user_id,
user_name=user_name,
installation_id=installation_id,
email=email,
)
first_issue = True
elif supabase_manager.is_users_first_issue(
supabase_manager.upsert_user(user_id=user_id, user_name=user_name, email=user_email)
supabase_manager.upsert_user_installation(
user_id=user_id, installation_id=installation_id
)
if supabase_manager.is_users_first_issue(
user_id=user_id, installation_id=installation_id
):
first_issue = True
Expand Down Expand Up @@ -771,14 +767,21 @@ def update_comment(
response.raise_for_status()
return response.json()


@handle_exceptions(default_return_value=None, raise_on_error=False)
def get_user_public_email(username: str, token: str) -> str | None:
"""https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#get-a-user"""
# If the user is a bot, the email is not available.
if "[bot]" in username:
return None

# If the user is not a bot, get the user's email
response: requests.Response = requests.get(
url=f"{GITHUB_API_URL}/users/{username}",
headers=create_headers(token=token),
timeout=TIMEOUT,
)
response.raise_for_status()
user_data: dict = response.json()
email: str | None = user_data.get('email')
email: str | None = user_data.get("email")
return email
64 changes: 24 additions & 40 deletions services/supabase/gitauto_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def create_installation(
owner_id: int,
user_id: int,
user_name: str,
email: str,
email: str | None,
) -> None:
"""Create owners record with stripe customerId, subscribe to free plan, create installation record, create users record on Installation Webhook event"""
# If owner doesn't exist in owners table, insert owner and stripe customer
Expand Down Expand Up @@ -71,20 +71,6 @@ def create_installation(
json={"owner_id": owner_id, "stripe_customer_id": customer_id}
).execute()

users_manager = UsersManager(client=self.client)
if users_manager.user_exists(user_id=user_id):
users_manager.handle_user_email_update(
user_id=user_id,
email=email
)
else:
# Create the user if it doesn't exist
users_manager.create_user(
user_id=user_id,
user_name=user_name,
installation_id=installation_id,
email=email,
)
# Insert installation record
self.client.table(table_name="installations").insert(
json={
Expand All @@ -94,29 +80,24 @@ def create_installation(
"owner_id": owner_id,
}
).execute()
# Create User, and set is_selected to True if user has no selected account for this installation
is_selected = True
data, _ = (
self.client.table(table_name="user_installations")
.select("user_id")
.eq(column="user_id", value=user_id)
.eq(column="is_selected", value=True)
.execute()
)
if len(data[1]) > 0:
is_selected = False

self.client.table(table_name="user_installations").insert(
json={
"user_id": user_id,
"installation_id": installation_id,
"is_selected": is_selected,
}
).execute()
# Upsert user
users_manager = UsersManager(client=self.client)
users_manager.upsert_user(user_id=user_id, user_name=user_name, email=email)

# Upsert user installation record
users_manager.upsert_user_installation(
user_id=user_id, installation_id=installation_id
)

@handle_exceptions(default_return_value=None, raise_on_error=True)
def create_user_request(
self, user_id: int, installation_id: int, unique_issue_id: str, email: str
self,
user_id: int,
user_name: str,
installation_id: int,
unique_issue_id: str,
email: str | None,
) -> int:
"""Creates record in usage table for this user and issue."""
# If issue doesn't exist, create one
Expand All @@ -126,14 +107,13 @@ def create_user_request(
.eq(column="unique_id", value=unique_issue_id)
.execute()
)

# If no issue exists with that unique_issue_id, create one
if not data[1]:
self.client.table(table_name="issues").insert(
json={
"unique_id": unique_issue_id,
"installation_id": installation_id,
}
json={"unique_id": unique_issue_id, "installation_id": installation_id}
).execute()

# Add user request to usage table
data, _ = (
self.client.table(table_name="usage")
Expand All @@ -146,9 +126,13 @@ def create_user_request(
)
.execute()
)

# Upsert user
users_manager = UsersManager(client=self.client)
if users_manager.user_exists(user_id=user_id):
users_manager.handle_user_email_update(user_id=user_id, email=email)
users_manager.upsert_user(user_id=user_id, user_name=user_name, email=email)
users_manager.upsert_user_installation(
user_id=user_id, installation_id=installation_id
)
return data[1][0]["id"]

@handle_exceptions(default_return_value=None, raise_on_error=False)
Expand Down
97 changes: 42 additions & 55 deletions services/supabase/users_manager.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
# Standard imports
import logging
from datetime import datetime
from typing import Any

# Third Party imports
import stripe
from supabase import Client

# Local imports
from config import DEFAULT_TIME, GITHUB_NOREPLY_EMAIL_DOMAIN, STRIPE_FREE_TIER_PRICE_ID, TZ
from config import (
DEFAULT_TIME,
GITHUB_NOREPLY_EMAIL_DOMAIN,
STRIPE_FREE_TIER_PRICE_ID,
TZ,
)
from services.stripe.customer import (
get_subscription,
get_request_count_from_product_id_metadata,
Expand All @@ -21,39 +27,16 @@ class UsersManager:

def __init__(self, client: Client) -> None:
self.client: Client = client

def check_email_is_valid(self, email: str) -> bool:
"""Check if email is valid"""

def check_email_is_valid(self, email: str | None) -> bool:
if email is None:
return False
if not isinstance(email, str):
return False
if "@" not in email or "." not in email:
return False
if str(email).lower().endswith(GITHUB_NOREPLY_EMAIL_DOMAIN):
return False
return True

@handle_exceptions(default_return_value=None, raise_on_error=False)
def create_user(self, user_id: int, user_name: str, installation_id: int, email: str) -> None:
"""Creates an account for the user in the users table"""
email = email if self.check_email_is_valid(email=email) else None
self.client.table(table_name="users").upsert(
json={
"user_id": user_id,
"user_name": user_name,
"email": email,
},
on_conflict="user_id"
).execute()

self.client.table(table_name="user_installations").insert(
json={
"user_id": user_id,
"installation_id": installation_id,
}
).execute()

# Check if user has a seat in an org or can be given a seat
@handle_exceptions(default_return_value=True, raise_on_error=False)
def is_user_eligible_for_seat_handler(
Expand Down Expand Up @@ -231,22 +214,8 @@ def get_how_many_requests_left_and_cycle(
end_date,
)

@handle_exceptions(default_return_value=False, raise_on_error=False)
def user_exists(self, user_id: int) -> bool:
"""Check if user exists in users table"""
data, _ = (
self.client.table(table_name="users")
.select("*")
.eq(column="user_id", value=user_id)
.execute()
)
if len(data[1]) > 0:
return True
return False


@handle_exceptions(default_return_value=False, raise_on_error=False)
def get_user_info(self, user_id: int) -> dict:
@handle_exceptions(default_return_value=None, raise_on_error=False)
def get_user(self, user_id: int):
"""Get user info from the users table"""
data, _ = (
self.client.table(table_name="users")
Expand All @@ -255,16 +224,34 @@ def get_user_info(self, user_id: int) -> dict:
.execute()
)
if len(data[1]) > 0:
return data[1][0]
return {}


@handle_exceptions(default_return_value=None, raise_on_error=True)
def handle_user_email_update(self, user_id: int, email: str) -> None:
"""Update user email in the users table if email is valid and not None and different from the current email"""
if self.check_email_is_valid(email=email):
user_info = self.get_user_info(user_id=user_id)
if user_info.get("email") != email:
self.client.table("users").update(
json={"email": email}
).eq("user_id", user_id).execute()
user: dict[str, Any] = data[1][0]
return user
return None

@handle_exceptions(default_return_value=None, raise_on_error=False)
def upsert_user(self, user_id: int, user_name: str, email: str | None) -> None:
# Check if email is valid
email = email if self.check_email_is_valid(email=email) else None

# Upsert user
self.client.table(table_name="users").upsert(
json={
"user_id": user_id,
"user_name": user_name,
**({"email": email} if email else {}),
"created_by": str(user_id), # Because created_by is text
},
on_conflict="user_id",
).execute()

@handle_exceptions(default_return_value=None, raise_on_error=False)
def upsert_user_installation(self, user_id: int, installation_id: int) -> None:
# Insert user installation record
self.client.table(table_name="user_installations").upsert(
json={
"user_id": user_id,
"installation_id": installation_id,
"is_selected": True,
},
on_conflict="user_id,installation_id",
).execute()
6 changes: 3 additions & 3 deletions services/webhook_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
create_comment_on_issue_with_gitauto_button,
get_installation_access_token,
# turn_on_issue,
get_user_public_email
get_user_public_email,
)
from services.github.github_types import GitHubInstallationPayload
from services.supabase import SupabaseManager
Expand All @@ -39,7 +39,7 @@ async def handle_installation_created(payload: GitHubInstallationPayload) -> Non
user_id: int = payload["sender"]["id"]
user_name: str = payload["sender"]["login"]
token: str = get_installation_access_token(installation_id=installation_id)
email: str | None = get_user_public_email(username=user_name, token=token)
user_email: str | None = get_user_public_email(username=user_name, token=token)

# Create installation record in Supabase
supabase_manager.create_installation(
Expand All @@ -49,7 +49,7 @@ async def handle_installation_created(payload: GitHubInstallationPayload) -> Non
owner_id=owner_id,
user_id=user_id,
user_name=user_name,
email=email,
email=user_email,
)

# Add issue templates to the repositories
Expand Down
Loading

0 comments on commit 9e78a62

Please sign in to comment.