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

Fix image upload on articles #1126

Merged

Conversation

NiallJoeMaher
Copy link
Contributor

✨ Codu Pull Request 💻

Pull Request details

Fix image upload on articles

  • Adds safe actions for actions
  • Uses actions instead of trpc

Adds safe actions for actions
Uses actions instead of trpc
@NiallJoeMaher NiallJoeMaher requested a review from a team as a code owner October 15, 2024 08:43
Copy link

vercel bot commented Oct 15, 2024

@NiallJoeMaher is attempting to deploy a commit to the Codú Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

coderabbitai bot commented Oct 15, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

The changes in this pull request involve significant modifications to the Create component by removing the session prop and refactoring the getUploadUrl function for improved error handling and direct URL retrieval. A new server-side action for generating presigned URLs has been introduced in getUploadUrl.ts, which includes input validation. Additionally, the profile.ts file has been streamlined by removing an unused import, and a new safeAction.ts file has been created to facilitate safe action clients with authentication checks.

Changes

File Path Change Summary
app/(app)/create/[[...paramsArr]]/_client.tsx Removed session prop from Create component; refactored getUploadUrl for direct URL retrieval and enhanced error handling. Updated handleUpload to use new getUploadUrl method.
app/actions/getUploadUrl.ts Introduced new file defining getUploadUrl server-side action with input validation and error tracking.
server/api/router/profile.ts Removed emailChangeHistory import; retained existing logic for user profile management.
server/lib/safeAction.ts Created new file for safeAction functionality, exporting authActionClient for authenticated actions.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CreateComponent
    participant UploadService
    participant AuthService

    User->>CreateComponent: Initiate Upload
    CreateComponent->>UploadService: Request Upload URL
    UploadService->>AuthService: Validate User Session
    AuthService-->>UploadService: Return Session Info
    UploadService-->>CreateComponent: Provide Presigned URL
    CreateComponent->>User: Display Upload URL
Loading

🐰 "In the code we weave, with care and delight,
Changes abound, making things right.
Uploads now flow, with ease and with grace,
A new path has opened, a bright, happy space!
With actions now safe, and sessions in check,
We hop through the code, what a joyful trek!" 🐇✨

Possibly related PRs

  • Fix image upload on articles #1126: This PR directly modifies the Create component in the same file as the main PR, addressing similar changes to the getUploadUrl function and the removal of the session dependency, indicating a strong relationship between the two.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (8)
server/lib/safeAction.ts (1)

7-15: Excellent implementation of authenticated action client.

The authActionClient setup effectively ensures that only authenticated users can execute actions, which is crucial for secure image uploads. The error handling and user context passing are well-implemented.

Consider enhancing the error message to provide more context:

- throw new Error("Session invalid.");
+ throw new Error("Authentication required. Please log in to perform this action.");

This more descriptive error message could help in debugging and provide clearer feedback if exposed to the user interface.

server/api/router/profile.ts (4)

Line range hint 25-63: Consider renaming the edit procedure for clarity.

The edit procedure handles various aspects of profile updates, including newsletter subscription management. While the implementation looks correct, a more descriptive name like updateProfileSettings might better reflect its functionality.


Line range hint 64-81: LGTM: Profile photo URL update logic.

The updateProfilePhotoUrl procedure correctly updates the user's profile image URL and includes a unique identifier to prevent caching issues. Consider adding a comment explaining the purpose of appending the unique identifier to the URL for better code documentation.


Line range hint 82-117: Consider moving accepted formats to a constant.

The getUploadUrl procedure correctly handles file type and size validation before generating a presigned URL. To improve maintainability, consider moving the acceptedFormats array to a constant, possibly in a separate configuration file.


Line range hint 133-201: Consider improving error message for existing email.

The updateEmail procedure includes comprehensive checks and validations for email change requests. However, the error message for an existing email ("Unable to process the request") could be more descriptive without revealing sensitive information.

Consider updating the error message to something like:

message: "This email address cannot be used. Please try a different one.",

This provides more context to the user without disclosing that the email is already in use.

app/(app)/create/[[...paramsArr]]/_client.tsx (1)

97-98: Consider resetting the file input after successful upload

After a successful upload, you might want to reset the file input to clear the selected file, improving the user experience.

Apply this diff to reset the file input:

    setUploadStatus("success");
    setUploadUrl(fileLocation);
+   e.target.value = "";
app/actions/getUploadUrl.ts (2)

28-30: Use a constant for the maximum file size for clarity

Instead of hardcoding 1048576 * 10, define a constant for the maximum file size to enhance readability and maintainability.

Apply this diff:

+     const MAX_FILE_SIZE = 1048576 * 10; // 10 MB
      if (size > 1048576 * 10) {
          throw new Error("Maximum file size 10mb");
      }

And update the condition:

-     if (size > 1048576 * 10) {
+     if (size > MAX_FILE_SIZE) {
          throw new Error("Maximum file size 10mb");
      }

39-43: Avoid logging errors to the console in production

Logging errors to the console can expose sensitive information in a production environment. Since the error is already captured by Sentry, consider removing the console.error statement.

Apply this diff:

          Sentry.captureException(error);
-         console.error("Error getting presigned URL:", error);
          throw new Error("Failed to upload image.");
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 9803fd1 and b24eb36.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json, !**/*.json
  • package.json is excluded by !**/*.json
📒 Files selected for processing (4)
  • app/(app)/create/[[...paramsArr]]/_client.tsx (2 hunks)
  • app/actions/getUploadUrl.ts (1 hunks)
  • server/api/router/profile.ts (1 hunks)
  • server/lib/safeAction.ts (1 hunks)
🧰 Additional context used
🔇 Additional comments (10)
server/lib/safeAction.ts (2)

1-5: LGTM! Well-structured setup for safe actions.

The imports and basic setup are well-organized and align perfectly with the PR objective of introducing safe actions for handling image uploads. The use of the "server-only" directive ensures proper security by restricting this code to server-side execution.


1-15: Excellent implementation of safe actions for image uploads.

This new file successfully introduces safe actions for handling image uploads, directly addressing the PR objectives. The implementation is concise, well-structured, and follows best practices for server-side security.

Key strengths:

  1. Server-only execution ensures sensitive operations are protected.
  2. Integration with existing authentication system.
  3. Proper error handling for unauthenticated requests.

This implementation provides a solid foundation for secure image upload handling in the Codu platform.

server/api/router/profile.ts (3)

Line range hint 118-132: LGTM: User profile retrieval logic.

The get procedure correctly retrieves a user profile based on the provided username and includes appropriate error handling for non-existent profiles.


Line range hint 1-201: Overall, the profileRouter implementation is robust and well-structured.

The changes made to this file (removal of unused import) are appropriate and do not negatively impact the functionality. The procedures within the profileRouter are well-implemented with proper input validation, error handling, and security considerations such as rate limiting.

Minor suggestions have been made for improving naming conventions, error messages, and code organization, but these are not critical issues. The current implementation should work as intended for handling various profile-related operations.


1-1: LGTM: Removal of unused import.

The removal of the unused emailChangeHistory import improves code cleanliness. This change is appropriate as the import is not used within this file.

Let's verify that emailChangeHistory is not used elsewhere in the codebase:

✅ Verification successful

LGTM: Removal of unused import.

The removal of the unused emailChangeHistory import in server/api/router/profile.ts improves code cleanliness and has no impact on other parts of the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining usages of emailChangeHistory in the codebase

# Test: Search for emailChangeHistory usage
rg --type typescript 'emailChangeHistory'

Length of output: 76


Script:

#!/bin/bash
# Description: Check for any remaining usages of emailChangeHistory in TypeScript files

# Test: Search for emailChangeHistory usage in .ts and .tsx files
rg 'emailChangeHistory' --glob '*.ts' --glob '*.tsx'

Length of output: 516

app/(app)/create/[[...paramsArr]]/_client.tsx (4)

32-32: Import statement is appropriate

The import of getUploadUrl from "@/app/actions/getUploadUrl" is correctly added and aligns with the usage in the code.


34-34: Removal of session prop is appropriate

The Create component no longer requires the session prop, simplifying its signature. This change is acceptable if the session is not used within the component.


74-82: ⚠️ Potential issue

Verify the response structure of getUploadUrl

In line 75, getUploadUrl is called, and in line 81, you're accessing res?.data to get the signedUrl. Please verify that getUploadUrl returns an object with a data property containing the signedUrl. If getUploadUrl returns the signed URL directly, you should assign it directly without accessing data.

Run the following script to verify the return value of getUploadUrl:


90-96: ⚠️ Potential issue

Ensure correct handling of uploadFile response

In line 90, you're destructuring { fileLocation } from the response of uploadFile(signedUrl, file). Please verify that uploadFile returns an object containing fileLocation. If it returns the file location directly or under a different property name, you may need to adjust the destructuring accordingly.

Run the following script to verify the return value of uploadFile function:

app/actions/getUploadUrl.ts (1)

15-44: Verify all usages of getUploadUrl handle the new validation correctly

Ensure that all calls to getUploadUrl properly handle the new validations for type and size, and that appropriate error handling is in place where this action is used.

Run the following script to find all usages of getUploadUrl:

Comment on lines 100 to 106
setUploadStatus("error");
toast.error(
error instanceof Error
? error.message
: "An error occurred while uploading the image.",
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Include error logging for better debugging

In your catch block, consider logging the error using Sentry or console logging. This can aid in debugging issues that occur during the upload process.

Apply this diff to log the error:

  } catch (error) {
    setUploadStatus("error");
    toast.error(
      error instanceof Error
        ? error.message
        : "An error occurred while uploading the image.",
    );
+   Sentry.captureException(error);
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
setUploadStatus("error");
toast.error(
error instanceof Error
? error.message
: "An error occurred while uploading the image.",
);
}
setUploadStatus("error");
toast.error(
error instanceof Error
? error.message
: "An error occurred while uploading the image.",
);
Sentry.captureException(error);
}

Comment on lines +18 to +20
const { type, size, uploadType } = parsedInput;
const extension = type.split("/")[1];
const acceptedFormats = ["jpg", "jpeg", "gif", "png", "webp"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure type contains a slash to prevent potential errors

In line 19, extension is derived using type.split("/")[1]. If type does not contain a " / ", extension will be undefined, which may cause issues when checking acceptedFormats. Consider validating that type includes a slash before splitting or handling the case where extension is undefined.

Apply this diff to add validation:

+     if (!type.includes('/')) {
+       throw new Error("Invalid file type format.");
+     }
      const extension = type.split("/")[1];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { type, size, uploadType } = parsedInput;
const extension = type.split("/")[1];
const acceptedFormats = ["jpg", "jpeg", "gif", "png", "webp"];
const { type, size, uploadType } = parsedInput;
if (!type.includes('/')) {
throw new Error("Invalid file type format.");
}
const extension = type.split("/")[1];
const acceptedFormats = ["jpg", "jpeg", "gif", "png", "webp"];

@NiallJoeMaher NiallJoeMaher merged commit a47e8d2 into codu-code:develop Oct 15, 2024
3 checks passed
@NiallJoeMaher NiallJoeMaher deleted the bugfix/article-image-uplaods branch October 15, 2024 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant