Skip to content

Show error if user didn't give correct Gmail permissions#242

Merged
elie222 merged 4 commits intomainfrom
permissions-error
Oct 11, 2024
Merged

Show error if user didn't give correct Gmail permissions#242
elie222 merged 4 commits intomainfrom
permissions-error

Conversation

@elie222
Copy link
Owner

@elie222 elie222 commented Oct 10, 2024

Summary by CodeRabbit

  • New Features

    • Introduced a PermissionsCheck component for validating user permissions before accessing certain pages.
    • Added a PermissionsErrorPage to inform users when they lack necessary permissions.
  • Bug Fixes

    • Enhanced error handling in the ErrorDisplay component to check for specific error messages.
  • Chores

    • Updated permissions-related utilities to improve permission checking and session handling.

@vercel
Copy link

vercel bot commented Oct 10, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
inbox-zero ✅ Ready (Inspect) Visit Preview Oct 10, 2024 11:47pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 10, 2024

Caution

Review failed

The head commit changed during the review from 3ea589b to 3f5ff0c.

Walkthrough

A new React component, PermissionsCheck, has been introduced to validate user permissions upon mounting and redirect to an error page if necessary. This component has been integrated into several pages, including AutomationPage, BulkUnsubscribePage, ColdEmailBlockerPage, Mail, and StatsPage, ensuring permission checks are performed before rendering main content. Additionally, a new PermissionsErrorPage component has been created to display an error message for users lacking permissions. Utility functions for checking permissions have also been added or modified.

Changes

File Path Change Summary
apps/web/app/(app)/PermissionsCheck.tsx Introduced PermissionsCheck component for permission validation and redirection.
apps/web/app/(app)/automation/page.tsx Imported and added PermissionsCheck to AutomationPage.
apps/web/app/(app)/bulk-unsubscribe/page.tsx Modified BulkUnsubscribePage to include PermissionsCheck.
apps/web/app/(app)/cold-email-blocker/page.tsx Imported and added PermissionsCheck to ColdEmailBlockerPage.
apps/web/app/(app)/mail/page.tsx Imported and rendered PermissionsCheck at the top of Mail component.
apps/web/app/(app)/permissions/error/page.tsx Introduced PermissionsErrorPage for displaying permission error messages.
apps/web/app/(app)/stats/page.tsx Modified StatsPage to include PermissionsCheck.
apps/web/components/ErrorDisplay.tsx Enhanced error handling in ErrorDisplay and simplified NotLoggedIn component signature.
apps/web/utils/actions/permissions.ts Introduced checkPermissionsAction for checking user permissions.
apps/web/utils/auth.ts Exported SCOPES constant and modified Session and JWT interfaces for improved usability.
apps/web/utils/gmail/permissions.ts Introduced checkGmailPermissions function for checking Gmail permissions based on access token.

Possibly related PRs

  • Add bulk actions #223: The BulkUnsubscribePage and other components in the bulk unsubscribe feature have been modified to include the PermissionsCheck component, indicating a direct relationship with the main PR's introduction of permission checks.

🐇 In the garden of code, we hop and play,
With PermissionsCheck, we keep errors at bay.
A sprinkle of checks, a dash of delight,
Ensuring each user is granted their right.
So here’s to the changes, both clever and bright,
In the world of permissions, we’ll shine like the light! ✨


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 (19)
apps/web/app/(app)/PermissionsCheck.tsx (2)

10-14: Consider adding error handling to the permissions check.

The permissions check and redirection logic are implemented correctly. However, it's advisable to add error handling to the promise chain to gracefully handle any potential errors during the permissions check.

Consider adding a .catch() block to handle potential errors:

 useEffect(() => {
   checkPermissionsAction().then((result) => {
     if (!result?.hasAllPermissions) router.replace("/permissions/error");
-  });
+  }).catch((error) => {
+    console.error("Error checking permissions:", error);
+    // Consider redirecting to an error page or showing an error message
+  });
 }, [router]);

1-17: Overall, the PermissionsCheck component is well-implemented with a minor suggestion for improvement.

The component effectively checks user permissions upon mounting and redirects to an error page if necessary. It's designed to be easily integrated into other parts of the application. The use of React hooks and Next.js routing is appropriate and well-implemented.

To further enhance the robustness of this component, consider implementing error handling for the permissions check as suggested earlier. This will ensure that any unexpected issues during the check are gracefully handled, improving the overall reliability of the application.

As this component is likely to be used across multiple pages, ensure it's placed in a common layout or wrapped around the main content in each relevant page to maintain consistent permission checking throughout the application.

apps/web/utils/actions/permissions.ts (1)

11-26: LGTM: Well-structured implementation with comprehensive error handling.

The checkPermissionsAction function is well-implemented with a logical flow of checks (session -> token -> permissions) and comprehensive error handling. The use of early returns for error cases is a good practice.

Consider using more specific error types or error codes to make it easier for the client to handle different error scenarios programmatically. For example:

type ErrorResponse = 
  | { error: "NOT_LOGGED_IN" }
  | { error: "NO_GMAIL_TOKEN" }
  | { error: "PERMISSION_CHECK_FAILED", details: string };

type SuccessResponse = { hasAllPermissions: boolean };

type ActionResponse = ErrorResponse | SuccessResponse;

// Then in the function:
if (!session?.user.id) return { error: "NOT_LOGGED_IN" };
// ...
if (!token.token) return { error: "NO_GMAIL_TOKEN" };
// ...
if (error) return { error: "PERMISSION_CHECK_FAILED", details: error };

This approach would provide more structured and type-safe error handling.

apps/web/app/(app)/permissions/error/page.tsx (3)

8-34: LGTM: Component structure is clean and responsive.

The component is well-structured and uses flex layout appropriately for centering content. The responsive padding classes (sm:p-20 md:p-32) provide good support for different screen sizes.

Consider adding a main tag around the content for better semantic structure and accessibility:

 export default function PermissionsErrorPage() {
   return (
+    <main>
       <div className="flex flex-col items-center justify-center sm:p-20 md:p-32">
         {/* ... content ... */}
       </div>
+    </main>
   );
 }

11-18: LGTM: Error message is clear and well-formatted.

The error message effectively communicates the issue and necessary actions to the user. The use of custom typography components ensures consistent styling across the application.

Consider extracting the text content into constants or using an internationalization library for easier maintenance and potential future localization:

const ERROR_HEADING = "You are missing permissions 😔";
const ERROR_MESSAGE = "You must sign in and give access to all permissions for Inbox Zero to work.";

// Then use these constants in your JSX
<PageHeading className="text-center">{ERROR_HEADING}</PageHeading>
<TypographyP className="mx-auto mt-4 max-w-prose text-center">
  {ERROR_MESSAGE}
</TypographyP>

20-22: LGTM: Sign in button is functional and consistent with UI.

The button correctly uses the custom Button component and has an appropriate onClick handler.

For clarity, consider renaming the logOut function or adding a comment to explain why logging out is necessary for signing in again:

// Log out the user to clear any existing sessions before redirecting to login
const handleSignInAgain = () => logOut("/login");

// Then use this in your JSX
<Button className="mt-4" onClick={handleSignInAgain}>
  Sign in again
</Button>
apps/web/utils/gmail/permissions.ts (3)

1-15: LGTM! Consider enhancing error logging.

The function signature, TypeScript types, and initial error handling are well-implemented. Good job on importing SCOPES from a separate file for better maintainability.

Consider using a more descriptive error message for logging:

-    console.error("No access token available");
+    console.error("checkGmailPermissions: No access token provided");

17-31: LGTM! Consider using a constant for the API URL.

The API call and response handling are well-implemented. Good job on proper error handling and use of async/await.

Consider extracting the API URL into a constant at the top of the file for better maintainability:

const GOOGLE_TOKEN_INFO_URL = "https://www.googleapis.com/oauth2/v1/tokeninfo";

// Then in the fetch call:
const response = await fetch(`${GOOGLE_TOKEN_INFO_URL}?access_token=${accessToken}`);

42-49: LGTM! Consider enhancing error logging.

The catch block appropriately handles exceptions and returns a safe default response.

Consider adding more context to the error log:

-    console.error("Error checking Gmail permissions:", error);
+    console.error("checkGmailPermissions: Error during API call or response processing:", error);
apps/web/components/ErrorDisplay.tsx (3)

47-47: Approved: Simplified component signature

The removal of the empty props object from the NotLoggedIn component signature is a good improvement. It makes the component more straightforward and easier to understand.

Consider using an arrow function with an implicit return for even more conciseness:

export const NotLoggedIn = () => (
  <div className="flex flex-col items-center justify-center sm:p-20 md:p-32">
    {/* ... component content ... */}
  </div>
);

Line range hint 37-43: Consider renaming the NotFound component

While there are no changes to this component, its name "NotFound" might be slightly misleading. It's used for general error display, not just 404 (Not Found) errors.

Consider renaming this component to something more general, such as ErrorPanel or ErrorWrapper, to better reflect its purpose:

const ErrorPanel = (props: { children: React.ReactNode }) => {
  return (
    <div className="text-gray-700">
      <Panel>{props.children}</Panel>
    </div>
  );
};

This change would make the component's purpose clearer and improve the overall readability of the code.


ErrorDisplay component lacks the enhanced error handling logic

The current implementation of the ErrorDisplay component does not include the enhanced error handling logic as described in the AI summary. Please implement the necessary enhancements to ensure consistent error handling.

🔗 Analysis chain

Line range hint 9-36: Verify changes to ErrorDisplay component

The AI summary mentions enhancements to the error handling logic in the ErrorDisplay component, but these changes are not visible in the provided code. Please verify if these changes have been implemented as described in the summary.

To confirm the current state of the ErrorDisplay component, please run the following script:

If the changes described in the AI summary are not present, please update the component to include the enhanced error handling logic.


If the above script still results in an error, please run the following fallback script without specifying the --type:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the current implementation of the ErrorDisplay component

# Test: Display the content of the ErrorDisplay component
rg --type typescript -A 30 'export function ErrorDisplay' apps/web/components/ErrorDisplay.tsx

Length of output: 131


Script:

#!/bin/bash
# Description: Corrected script to verify the current implementation of the ErrorDisplay component

# Test: Display the content of the ErrorDisplay component
rg --type typescriptreact -A 30 'export function ErrorDisplay' apps/web/components/ErrorDisplay.tsx

Length of output: 141


Script:

#!/bin/bash
# Description: Corrected script to verify the current implementation of the ErrorDisplay component using the correct type

# Test: Display the content of the ErrorDisplay component
rg --type tsx -A 30 'export function ErrorDisplay' apps/web/components/ErrorDisplay.tsx

Length of output: 117


Script:

#!/bin/bash
# Description: Fallback script to verify the current implementation of the ErrorDisplay component without using --type

# Test: Display the content of the ErrorDisplay component
rg 'export function ErrorDisplay' apps/web/components/ErrorDisplay.tsx -A 30

Length of output: 828

apps/web/app/(app)/cold-email-blocker/page.tsx (1)

8-13: Overall impact: Permissions check successfully implemented

The addition of the PermissionsCheck component effectively introduces a permissions validation mechanism to the ColdEmailBlockerPage, aligning with the PR objective. The implementation is clean and non-intrusive, preserving the existing functionality of the page.

As a minor suggestion for improvement:

Consider adding a comment explaining the purpose of the PermissionsCheck component, especially if it's being used across multiple pages. This would enhance code readability and maintainability. For example:

// Validate user permissions and redirect to error page if necessary
<PermissionsCheck />
apps/web/app/(app)/mail/page.tsx (1)

Line range hint 62-63: Consider alternative to storing refetch in atom

The current implementation stores the refetch function in an atom for global access. While this works, it might not be the most maintainable or scalable solution. Consider these alternatives:

  1. Use React Context to provide the refetch function to child components.
  2. If using a state management library like Redux, store the refetch function there.
  3. Create a custom hook that encapsulates the email list fetching logic and provides the refetch function.

Example of a custom hook approach:

function useEmailList(query: ThreadsQuery) {
  const { data, isLoading, error, mutate } = useSWR<ThreadsResponse>(
    `/api/google/threads?${new URLSearchParams(query as any).toString()}`,
    {
      keepPreviousData: true,
      dedupingInterval: 1_000,
    }
  );

  const refetch = useCallback(
    (removedThreadIds?: string[]) => {
      // ... existing refetch logic ...
    },
    [mutate]
  );

  return { data, isLoading, error, refetch };
}

This approach would encapsulate the fetching logic and make it reusable across components.

apps/web/app/(app)/automation/page.tsx (1)

27-28: LGTM: PermissionsCheck component added

The PermissionsCheck component is correctly placed at the beginning of the render tree, ensuring permissions are validated before rendering the main content. This implementation aligns well with the PR objective.

Consider wrapping the rest of the component tree with an error boundary to gracefully handle any errors that might occur during the permissions check:

 <Suspense>
   <PermissionsCheck />
+  <ErrorBoundary fallback={<ErrorFallback />}>
     <Tabs defaultValue="prompt">
       {/* ... rest of the component ... */}
     </Tabs>
+  </ErrorBoundary>
 </Suspense>

This would provide a more robust error handling mechanism for any unexpected issues during the permissions check process.

apps/web/utils/auth.ts (4)

Line range hint 85-86: Ensure Consistent JWT Structure When Returning Errors

In the refreshAccessToken function, when no account is found, the function returns:

return { error: "MissingAccountError" };

Returning only the error property may lead to issues since other expected properties of the JWT token are missing. To maintain consistency and prevent potential errors in the authentication flow, consider spreading the existing token object.

Apply this diff to fix the issue:

- return { error: "MissingAccountError" };
+ return { ...token, error: "MissingAccountError" };

Line range hint 149-155: Avoid Using 'any' Type Assertion for Prisma Adapter

In the getAuthOptions function, the adapter is cast to any with a TODO comment:

adapter: PrismaAdapter(prisma) as any, // TODO

Using any bypasses TypeScript's type checking, which may lead to runtime errors. It's better to address the underlying type incompatibility.

Consider importing the correct type for the Prisma Adapter or adjusting the type definitions to match. Here's how you might fix it:

- import { PrismaAdapter } from "@auth/prisma-adapter";
+ import { PrismaAdapter } from "@next-auth/prisma-adapter";

Ensure that you are importing from the correct package and that the types are properly aligned.


Line range hint 194-198: Review Type Definition of Session.error Property

In the Session interface within the next-auth module declaration, the error property is defined as:

error?: string | "RefreshAccessTokenError";

Since RefreshAccessTokenError is a string literal, and string already includes all string values, including "RefreshAccessTokenError", specifying both is redundant.

Consider updating the type to:

- error?: string | "RefreshAccessTokenError";
+ error?: string;

Or, if you intend to restrict the error to specific values, define a union of string literals:

error?: "RefreshAccessTokenError" | "AnotherSpecificError";

Line range hint 201-206: Consider Generalizing JWT.error Property Type

In the JWT interface within the @auth/core/jwt module declaration, the error property is typed as:

error?: "RefreshAccessTokenError" | "MissingAccountError";

If you anticipate handling additional error types in the future, it might be more flexible to define error as a string.

Consider updating the type:

- error?: "RefreshAccessTokenError" | "MissingAccountError";
+ error?: string;

This change allows for greater flexibility in error handling.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between c45e67c and fe57064.

📒 Files selected for processing (11)
  • apps/web/app/(app)/PermissionsCheck.tsx (1 hunks)
  • apps/web/app/(app)/automation/page.tsx (1 hunks)
  • apps/web/app/(app)/bulk-unsubscribe/page.tsx (1 hunks)
  • apps/web/app/(app)/cold-email-blocker/page.tsx (1 hunks)
  • apps/web/app/(app)/mail/page.tsx (2 hunks)
  • apps/web/app/(app)/permissions/error/page.tsx (1 hunks)
  • apps/web/app/(app)/stats/page.tsx (1 hunks)
  • apps/web/components/ErrorDisplay.tsx (1 hunks)
  • apps/web/utils/actions/permissions.ts (1 hunks)
  • apps/web/utils/auth.ts (1 hunks)
  • apps/web/utils/gmail/permissions.ts (1 hunks)
🧰 Additional context used
🔇 Additional comments (21)
apps/web/app/(app)/stats/page.tsx (1)

1-12: LGTM! The changes align with the PR objective.

The addition of the PermissionsCheck component and its placement in the return statement effectively implements the requirement to show an error if the user didn't give correct Gmail permissions. The existing functionality with checkAndRedirectForUpgrade is preserved, ensuring a comprehensive check before rendering the main content.

To ensure consistency across the application, let's verify the implementation of PermissionsCheck and its usage in other pages:

apps/web/app/(app)/bulk-unsubscribe/page.tsx (3)

1-1: LGTM: New PermissionsCheck component added correctly

The PermissionsCheck component has been imported and integrated properly into the page. This addition aligns well with the PR objective of showing an error if the user didn't give correct Gmail permissions.

Also applies to: 9-9


7-12: LGTM: Return statement updated correctly

The return statement has been properly modified to include both the PermissionsCheck and BulkUnsubscribe components. The use of a React fragment is appropriate, and the order of components ensures that permissions are checked before rendering the main content.


1-12: Verify error handling for incorrect permissions

The addition of PermissionsCheck aligns with the PR objective. However, it's not immediately clear from this file how errors are displayed if the user hasn't given correct Gmail permissions.

Could you please clarify:

  1. How does PermissionsCheck handle and display errors?
  2. Is there any interaction between checkAndRedirectForUpgrade and the permissions check?

To verify the implementation, we can run the following script:

apps/web/app/(app)/PermissionsCheck.tsx (3)

1-6: LGTM: Imports and setup are correct.

The "use client" directive and imports are properly set up. The component correctly imports the necessary hooks from React and Next.js, as well as the custom action for checking permissions.


7-9: LGTM: Component declaration and hook initialization are correct.

The PermissionsCheck component is properly exported as a function component, and the useRouter hook is correctly initialized.


16-16: LGTM: Component correctly returns null.

The PermissionsCheck component appropriately returns null as it doesn't need to render any UI elements. Its purpose is solely to perform the permissions check and potential redirection as a side effect.

apps/web/utils/actions/permissions.ts (2)

1-7: LGTM: Server-side directive and imports are correctly implemented.

The "use server" directive is properly placed at the top of the file, and the imports seem relevant to the file's functionality. The use of withActionInstrumentation suggests good practices for monitoring and logging server actions.


8-10: LGTM: Action declaration and instrumentation wrapper.

The checkPermissionsAction is correctly exported and wrapped with withActionInstrumentation, which is good for monitoring purposes. The action name "checkPermissions" is clear and descriptive.

apps/web/app/(app)/permissions/error/page.tsx (1)

1-6: LGTM: Imports and dependencies are well-organized.

The "use client" directive is correctly placed, and all necessary dependencies are imported. The imports are logically organized, which enhances code readability.

apps/web/utils/gmail/permissions.ts (1)

33-41: LGTM! Efficient scope comparison logic.

The scope comparison logic is well-implemented. Good use of modern JavaScript features like optional chaining and nullish coalescing. The filter method for finding missing scopes is efficient and readable.

apps/web/app/(app)/cold-email-blocker/page.tsx (3)

8-8: LGTM: Import statement for PermissionsCheck

The import statement for the PermissionsCheck component is correctly implemented and follows React best practices.


13-13: LGTM: Addition of PermissionsCheck component

The <PermissionsCheck /> component is correctly placed as the first child of the Suspense component. This ensures that permissions are checked before rendering the rest of the page content, which aligns with the PR objective.


13-13: Verify error handling in PermissionsCheck component

While the placement of <PermissionsCheck /> is correct, it's important to ensure that it properly handles cases where the user lacks the necessary permissions.

Could you please confirm how the PermissionsCheck component handles errors and redirects users when permissions are insufficient? You can run the following script to inspect the PermissionsCheck component:

✅ Verification successful

PermissionsCheck handles permission errors correctly

Verified that the PermissionsCheck component redirects users to /permissions/error when permissions are insufficient using router.replace.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Inspect the PermissionsCheck component implementation

# Test: Search for the PermissionsCheck component definition
ast-grep --lang typescript --pattern 'export function PermissionsCheck() {
  $$$
}'

# Test: Search for any error handling or redirection logic within PermissionsCheck
rg --type typescript 'router\.push|useRouter|throw|Error' apps/web/app/\(app\)/PermissionsCheck.tsx

Length of output: 222


Script:

#!/bin/bash
# Description: Re-inspect the PermissionsCheck component implementation with adjusted search parameters

# Test: Search for the PermissionsCheck component definition by file extension
ast-grep --lang typescript --pattern 'export function PermissionsCheck() {
  $$$
}' 

# Test: Search for any error handling or redirection logic within PermissionsCheck using file extension
rg 'router\.push|useRouter|throw|Error' 'apps/web/app/(app)/PermissionsCheck.tsx' --glob '*.tsx' -A 2

Length of output: 359


Script:

#!/bin/bash
# Description: Further inspect the PermissionsCheck component for error handling and redirection logic

# Test: Search for usage of checkPermissionsAction within PermissionsCheck
rg 'checkPermissionsAction' 'apps/web/app/(app)/PermissionsCheck.tsx' --glob '*.tsx' -A 5

# Test: Search for any redirection methods other than router.push
rg 'router\.replace|router\.reload|router\.' 'apps/web/app/(app)/PermissionsCheck.tsx' --glob '*.tsx'

Length of output: 592

apps/web/app/(app)/mail/page.tsx (3)

13-13: LGTM: New import for PermissionsCheck

The import statement for the PermissionsCheck component is correctly added and follows the existing import conventions in the file.


Line range hint 1-87: Summary: Changes align with PR objectives

The addition of the PermissionsCheck component to the Mail page aligns well with the PR objective of showing an error if the user didn't give correct Gmail permissions. The implementation looks solid, with the component placed appropriately to ensure permissions are checked before rendering the main content.

A few points to consider for future improvements (not directly related to this PR):

  1. The suggested refactoring of the email list fetching logic into a custom hook.
  2. Ensuring consistent usage of PermissionsCheck across all relevant pages.

Overall, the changes achieve the intended goal and maintain the existing functionality of the Mail component.


74-74: Verify PermissionsCheck implementation

The PermissionsCheck component has been appropriately placed at the beginning of the JSX, ensuring that permissions are validated before rendering the main content. This aligns with the PR objective of showing an error if the user doesn't have correct Gmail permissions.

However, to ensure full functionality:

  1. Verify that the PermissionsCheck component correctly redirects to the error page when necessary.
  2. Confirm that it doesn't block the rendering of the main content when permissions are valid.

To verify the implementation, please run the following script:

apps/web/app/(app)/automation/page.tsx (2)

19-19: LGTM: New import for PermissionsCheck

The import statement for the PermissionsCheck component is correctly added and aligns with the PR objective to implement permission checks.


Line range hint 1-89: Summary: Effective implementation of permissions check

The changes in this file successfully implement the PR objective of showing an error if the user didn't give correct Gmail permissions. The PermissionsCheck component is appropriately imported and placed at the beginning of the render tree, ensuring that permissions are validated before rendering the main content of the AutomationPage.

These minimal changes effectively integrate the new functionality without disrupting the existing structure of the component. The implementation is clean and aligns well with React best practices.

apps/web/utils/auth.ts (2)

Line range hint 12-18: SCOPES Constant Exported and Defined Correctly

The SCOPES constant is correctly exported and includes all the necessary Google OAuth scopes. The conditional inclusion of the Contacts API scope based on env.NEXT_PUBLIC_CONTACTS_ENABLED is appropriate.


Line range hint 103-104: Ensure Consistent JWT Structure When Refresh Token Is Missing

Similarly, when the refresh token is not found in the database, the function returns:

return {
  ...token,
  error: "RefreshAccessTokenError",
};

This is appropriate as it maintains the existing token properties. Ensure consistency in error handling throughout the function.

Comment on lines +24 to +31
<div className="mt-8">
<Image
src="/images/falling.svg"
alt=""
width={400}
height={400}
unoptimized
/>
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

Improve image accessibility and consider performance optimization.

While using the Next.js Image component is good for performance, there are a few areas that could be improved:

  1. The empty alt attribute might not be ideal for accessibility. If the image is decorative, consider using alt=" " (with a space) instead of an empty string.
  2. The unoptimized prop bypasses Next.js's image optimization. Unless there's a specific reason for this, consider removing it to leverage Next.js's built-in image optimization.

Apply the following changes to improve accessibility and potentially enhance performance:

 <Image
   src="/images/falling.svg"
-  alt=""
+  alt=" "
   width={400}
   height={400}
-  unoptimized
 />

Also, consider using responsive image sizing if appropriate for your design:

<Image
  src="/images/falling.svg"
  alt=" "
  width={400}
  height={400}
  sizes="(max-width: 768px) 100vw, 400px"
/>

This allows the image to adapt to different screen sizes while maintaining the aspect ratio.

Comment on lines +1 to +50
import { SCOPES } from "@/utils/auth";

export async function checkGmailPermissions(accessToken: string): Promise<{
hasAllPermissions: boolean;
missingScopes: string[];
error?: string;
}> {
if (!accessToken) {
console.error("No access token available");
return {
hasAllPermissions: false,
missingScopes: SCOPES,
error: "No access token available",
};
}

try {
const response = await fetch(
`https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=${accessToken}`,
);

const data = await response.json();

if (data.error) {
console.error("Error checking Gmail permissions:", data.error);
return {
hasAllPermissions: false,
missingScopes: SCOPES, // Assume all scopes are missing if we can't check
error: data.error,
};
}

const grantedScopes = data.scope?.split(" ") || [];
const missingScopes = SCOPES.filter(
(scope) => !grantedScopes.includes(scope),
);

return {
hasAllPermissions: missingScopes.length === 0,
missingScopes,
};
} catch (error) {
console.error("Error checking Gmail permissions:", error);
return {
hasAllPermissions: false,
missingScopes: SCOPES, // Assume all scopes are missing if we can't check
error: "Failed to check permissions",
};
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Security Concern Confirmed: Sanitization of Error Logs Required

The review comment regarding the security implications of error logging has been validated. The checkGmailPermissions function in apps/web/utils/gmail/permissions.ts directly logs error objects, which can potentially expose sensitive information.

Affected Line:

  • apps/web/utils/gmail/permissions.ts: console.error("Error checking Gmail permissions:", error);

Recommendation:
Implement a sanitization function to ensure that only non-sensitive error messages are logged.

function sanitizeError(error: unknown): string {
  if (error instanceof Error) {
    return error.message;
  }
  return String(error);
}

// Usage:
console.error("Error checking Gmail permissions:", sanitizeError(error));
🔗 Analysis chain

Great implementation overall. Consider security implications of error logging.

The checkGmailPermissions function is well-implemented, with good error handling, proper use of TypeScript, and efficient logic. It effectively fulfills its purpose of checking Gmail permissions.

However, there's a potential security concern with logging error objects. These might contain sensitive information. Consider sanitizing the error logs:

If the script finds instances of logging error objects, consider implementing a sanitize function:

function sanitizeError(error: unknown): string {
  if (error instanceof Error) {
    return error.message;
  }
  return String(error);
}

// Usage:
console.error("Error checking Gmail permissions:", sanitizeError(error));

Action Required: Verify Sensitive Error Logging

The previous script encountered an error due to an unrecognized file type. Please use the corrected script below to check for potential sensitive data logging:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for potential sensitive data logging
rg --type typescript 'console\.(log|error|warn|info).*error' apps/web/

Length of output: 107


Script:

#!/bin/bash
# Check for potential sensitive data logging
rg --type ts 'console\.(log|error|warn|info).*error' apps/web/

Length of output: 3263

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

Comments