-
Notifications
You must be signed in to change notification settings - Fork 2
Changes to how users are added and deleted #235
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
Changes from all commits
67567c5
ae9b13e
8700d06
4275cdd
b42a0cc
9aaad16
e795681
6fbd1bc
8caf28f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| import binascii | ||
|
|
||
| import graphene | ||
| import base64 | ||
| import os | ||
|
|
@@ -32,6 +34,8 @@ | |
| import logging | ||
| from zoneinfo import ZoneInfo | ||
| from sqlalchemy import func, cast, Date | ||
| import boto3 | ||
| from botocore.exceptions import ClientError | ||
|
|
||
| local_tz = ZoneInfo("America/New_York") | ||
|
|
||
|
|
@@ -833,81 +837,103 @@ class Arguments: | |
| def mutate(self, info, name, net_id, email, encoded_image=None): | ||
| # Check if a user with the given NetID already exists | ||
| existing_user = db_session.query(UserModel).filter(UserModel.net_id == net_id).first() | ||
| final_photo_url = None | ||
| if existing_user: | ||
| raise GraphQLError("NetID already exists.") | ||
|
|
||
| final_photo_url = None | ||
|
|
||
| if encoded_image: | ||
| upload_url = os.getenv("DIGITAL_OCEAN_URL") | ||
| if not upload_url: | ||
| raise GraphQLError("Upload URL not configured.") | ||
|
|
||
| headers = {"Content-Type": "application/json"} | ||
| s3 = boto3.client( | ||
| "s3", | ||
| endpoint_url=os.getenv("DIGITAL_OCEAN_URL"), | ||
| aws_access_key_id=os.getenv("DIGITAL_OCEAN_ACCESS"), | ||
| aws_secret_access_key=os.getenv("DIGITAL_OCEAN_SECRET_ACCESS") | ||
| ) | ||
|
|
||
| image_bytes = base64.b64decode(encoded_image) | ||
| files = {"image": ("profile.png", image_bytes, "image/png")} | ||
| data = {"bucket": os.getenv("BUCKET_NAME")} | ||
| try: | ||
| response = requests.post(upload_url, files=files, data=data) | ||
| response.raise_for_status() | ||
| json_response = response.json() | ||
| final_photo_url = json_response.get("data") | ||
| if not final_photo_url: | ||
| raise GraphQLError("No URL returned from upload service.") | ||
| except requests.exceptions.RequestException as e: | ||
| print(f"Request failed: {e}") | ||
| raise GraphQLError(f"Failed to upload photo: {e}") | ||
| image_data = base64.b64decode(encoded_image, validate=True) | ||
| except (binascii.Error, ValueError) as err: | ||
| raise GraphQLError("Invalid profile image encoding.") | ||
|
|
||
| try: | ||
| bucket = "appdev-upload" | ||
| path = f"uplift-dev/user-profile/{net_id}-profile.png" | ||
| region = "nyc3" | ||
|
|
||
| s3.put_object( | ||
| Bucket=bucket, | ||
| Key=path, | ||
| Body=image_data, | ||
| ContentType="image/png", | ||
| ACL="public-read" | ||
| ) | ||
|
|
||
| final_photo_url = f"https://{bucket}.{region}.digitaloceanspaces.com/{path}" | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| except ClientError as e: | ||
| print("Upload error:", e) | ||
| raise GraphQLError("Error uploading user profile picture.") | ||
|
Comment on lines
+873
to
+875
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# First, let's check if the file exists and its size
wc -l src/schema.pyRepository: cuappdev/uplift-backend Length of output: 85 🏁 Script executed: #!/bin/bash
# Examine the code at the specified lines with context
echo "=== Lines 873-875 context ==="
sed -n '860,880p' src/schema.py | cat -n
echo -e "\n=== Lines 934-936 context ==="
sed -n '920,945p' src/schema.py | cat -n
echo -e "\n=== Lines 1211-1213 context ==="
sed -n '1200,1225p' src/schema.py | cat -nRepository: cuappdev/uplift-backend Length of output: 3470 Add exception chaining to S3 failure handlers. Three exception handlers re-raise without chaining the original Locations and suggested fixesLines 873-875: except ClientError as e:
print("Upload error:", e)
- raise GraphQLError("Error uploading user profile picture.")
+ raise GraphQLError("Error uploading user profile picture.") from eLines 934-936: except ClientError as e:
print("Upload error:", e)
- raise GraphQLError("Error adding new user profile picture.")
+ raise GraphQLError("Error adding new user profile picture.") from eLines 1211-1213: except ClientError as e:
print("Delete error:", e)
- raise GraphQLError("Error deleting user profile picture")
+ raise GraphQLError("Error deleting user profile picture") from e🧰 Tools🪛 Ruff (0.15.6)[warning] 875-875: Within an (B904) 🤖 Prompt for AI Agents |
||
|
|
||
| new_user = UserModel(name=name, net_id=net_id, email=email, encoded_image=final_photo_url) | ||
| db_session.add(new_user) | ||
| db_session.commit() | ||
|
|
||
| return new_user | ||
|
|
||
|
|
||
| class EditUser(graphene.Mutation): | ||
| class EditUserById(graphene.Mutation): | ||
| class Arguments: | ||
| user_id = graphene.Int(required=True) | ||
| name = graphene.String(required=False) | ||
| net_id = graphene.String(required=True) | ||
| email = graphene.String(required=False) | ||
| encoded_image = graphene.String(required=False) | ||
|
|
||
| Output = User | ||
|
|
||
| def mutate(self, info, net_id, name=None, email=None, encoded_image=None): | ||
| existing_user = db_session.query(UserModel).filter(UserModel.net_id == net_id).first() | ||
| @jwt_required() | ||
| def mutate(self, info, user_id, name=None, email=None, encoded_image=None): | ||
| existing_user = db_session.query(UserModel).filter(UserModel.id == user_id).first() | ||
|
|
||
| if not existing_user: | ||
| raise GraphQLError("User with given net id does not exist.") | ||
|
|
||
| raise GraphQLError("User with given id does not exist.") | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if get_jwt_identity() != user_id: | ||
| raise GraphQLError("Unauthorized operation") | ||
| if name is not None: | ||
| existing_user.name = name | ||
| if email is not None: | ||
| existing_user.email = email | ||
| if encoded_image is not None: | ||
| upload_url = os.getenv("DIGITAL_OCEAN_URL") # Base URL for upload endpoint | ||
| if not upload_url: | ||
| raise GraphQLError("Upload URL not configured.") | ||
|
|
||
| payload = { | ||
| "bucket": os.getenv("BUCKET_NAME", "DEV_BUCKET"), | ||
| "image": encoded_image, # Base64-encoded image string | ||
| } | ||
| headers = {"Content-Type": "application/json"} | ||
|
|
||
| print(f"Uploading image with payload: {payload}") | ||
| final_photo_url = None | ||
| s3 = boto3.client( | ||
| "s3", | ||
| endpoint_url=os.getenv("DIGITAL_OCEAN_URL"), | ||
| aws_access_key_id=os.getenv("DIGITAL_OCEAN_ACCESS"), | ||
| aws_secret_access_key=os.getenv("DIGITAL_OCEAN_SECRET_ACCESS") | ||
| ) | ||
|
|
||
| try: | ||
| image_data = base64.b64decode(encoded_image, validate=True) | ||
| except (binascii.Error, ValueError) as err: | ||
| raise GraphQLError("Invalid profile image encoding.") | ||
|
|
||
| try: | ||
| response = requests.post(upload_url, json=payload, headers=headers) | ||
| response.raise_for_status() | ||
| json_response = response.json() | ||
| print(f"Upload API response: {json_response}") | ||
| final_photo_url = json_response.get("data") | ||
| if not final_photo_url: | ||
| raise GraphQLError("No URL returned from upload service.") | ||
| bucket = "appdev-upload" | ||
| path = f"uplift-dev/user-profile/{existing_user.net_id}-profile.png" | ||
| region = "nyc3" | ||
|
|
||
| s3.put_object( | ||
| Bucket=bucket, | ||
| Key=path, | ||
| Body=image_data, | ||
| ContentType="image/png", | ||
| ACL="public-read" | ||
| ) | ||
|
|
||
| final_photo_url = f"https://{bucket}.{region}.digitaloceanspaces.com/{path}" | ||
| existing_user.encoded_image = final_photo_url | ||
| except requests.exceptions.RequestException as e: | ||
| print(f"Request failed: {e}") | ||
| raise GraphQLError("Failed to upload photo.") | ||
| except ClientError as e: | ||
| print("Upload error:", e) | ||
| raise GraphQLError("Error adding new user profile picture.") | ||
|
|
||
| db_session.commit() | ||
| return existing_user | ||
|
|
@@ -1063,6 +1089,7 @@ def mutate(self, info, user_id, workout_goal): | |
|
|
||
| db_session.commit() | ||
| return user | ||
|
|
||
| class logWorkout(graphene.Mutation): | ||
| class Arguments: | ||
| workout_time = graphene.DateTime(required=True) | ||
|
|
@@ -1157,11 +1184,34 @@ class Arguments: | |
|
|
||
| Output = User | ||
|
|
||
| @jwt_required() | ||
| def mutate(self, info, user_id): | ||
| # Check if user exists | ||
| user = User.get_query(info).filter(UserModel.id == user_id).first() | ||
|
|
||
| if not user: | ||
| raise GraphQLError("User with given ID does not exist.") | ||
|
|
||
| if get_jwt_identity() != user_id: | ||
| raise GraphQLError("Unauthorized operation") | ||
|
|
||
| s3 = boto3.client( | ||
| "s3", | ||
| endpoint_url=os.getenv("DIGITAL_OCEAN_URL"), | ||
| aws_access_key_id=os.getenv("DIGITAL_OCEAN_ACCESS"), | ||
| aws_secret_access_key=os.getenv("DIGITAL_OCEAN_SECRET_ACCESS") | ||
| ) | ||
|
|
||
| if user.encoded_image: | ||
| try: | ||
| s3.delete_object( | ||
| Bucket="appdev-upload", | ||
| Key=f"uplift-dev/user-profile/{user.net_id}-profile.png", | ||
| ) | ||
| except ClientError as e: | ||
| print("Delete error:", e) | ||
| raise GraphQLError("Error deleting user profile picture") | ||
|
|
||
| db_session.delete(user) | ||
| db_session.commit() | ||
| return user | ||
|
|
@@ -1440,7 +1490,7 @@ def mutate(self, info, user_id): | |
| class Mutation(graphene.ObjectType): | ||
| create_giveaway = CreateGiveaway.Field(description="Creates a new giveaway.") | ||
| create_user = CreateUser.Field(description="Creates a new user.") | ||
| edit_user = EditUser.Field(description="Edit a new user.") | ||
| edit_user = EditUserById.Field(description="Edit a new user by id.") | ||
| enter_giveaway = EnterGiveaway.Field(description="Enters a user into a giveaway.") | ||
| set_workout_goals = SetWorkoutGoals.Field(description="Set a user's workout goals.") | ||
| log_workout = logWorkout.Field(description="Log a user's workout.") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's look at the file structure and find src/schema.py git ls-files src/schema.pyRepository: cuappdev/uplift-backend
Length of output: 80
🏁 Script executed:
Repository: cuappdev/uplift-backend
Length of output: 706
🏁 Script executed:
Repository: cuappdev/uplift-backend
Length of output: 719
🏁 Script executed:
Repository: cuappdev/uplift-backend
Length of output: 237
🏁 Script executed:
Repository: cuappdev/uplift-backend
Length of output: 93
🏁 Script executed:
Repository: cuappdev/uplift-backend
Length of output: 102
🏁 Script executed:
Repository: cuappdev/uplift-backend
Length of output: 322
🏁 Script executed:
Repository: cuappdev/uplift-backend
Length of output: 1911
🏁 Script executed:
# Check flake8 configuration cat .flake8Repository: cuappdev/uplift-backend
Length of output: 178
🏁 Script executed:
# Check pyproject.toml for any Python version or linting settings cat pyproject.tomlRepository: cuappdev/uplift-backend
Length of output: 182
🏁 Script executed:
Repository: cuappdev/uplift-backend
Length of output: 345
🏁 Script executed:
Repository: cuappdev/uplift-backend
Length of output: 344
Chain decode exceptions to fix lint and preserve root cause.
erris unused and the raisedGraphQLErrordrops the original exception context. Add exception chaining withfrom errat both locations.🛠️ Suggested fix
Also applies to: 916-917
🧰 Tools
🪛 Flake8 (7.3.0)
[error] 856-856: local variable 'err' is assigned to but never used
(F841)
🪛 Ruff (0.15.6)
[warning] 857-857: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
🤖 Prompt for AI Agents