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

♻️ Keep guest ids in separate column #1468

Merged
merged 6 commits into from
Dec 27, 2024
Merged

♻️ Keep guest ids in separate column #1468

merged 6 commits into from
Dec 27, 2024

Conversation

lukevella
Copy link
Owner

@lukevella lukevella commented Dec 24, 2024

Summary by CodeRabbit

  • New Features

    • Enhanced data structure for user identification in polls, allowing for guest participation.
    • Added guestId property to participant and comment data models.
    • Streamlined logic for comment deletion and user permissions.
    • Updated logic for filtering polls based on user type (guest or registered).
  • Bug Fixes

    • Improved permission checks for comment deletion and participant editing.
  • Documentation

    • Updated schema to reflect new guestId fields and adjustments to user associations.
  • Chores

    • Database migration to add guest_id columns and improve query performance with new indexes.

Copy link

vercel bot commented Dec 24, 2024

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

Name Status Preview Comments Updated (UTC)
app ✅ Ready (Inspect) Visit Preview 💬 Add feedback Dec 26, 2024 11:40am
1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
landing ⬜️ Skipped (Inspect) Dec 26, 2024 11:40am

Copy link
Contributor

coderabbitai bot commented Dec 24, 2024

Walkthrough

This pull request introduces comprehensive changes to support guest user functionality across the application. The modifications span multiple files and involve adding a new guestId field to various database models and components. The changes enable the system to handle both registered and guest users more flexibly, particularly in contexts like polls, comments, and participants. The implementation focuses on updating data structures, permission checks, and database schema to accommodate guest user interactions while maintaining existing functionality.

Changes

File Change Summary
apps/web/src/app/[locale]/(admin)/polls/user-polls.tsx Updated PollsListView data structure to use user object and added optional guestId.
apps/web/src/components/discussion/discussion.tsx Simplified permission checks using session.ownsObject(comment).
apps/web/src/components/poll/desktop-poll.tsx Added guestId to participant object passed to ParticipantRow.
apps/web/src/components/poll/desktop-poll/participant-row.tsx Added optional guestId to ParticipantRowProps and simplified user ownership check.
apps/web/src/components/user-provider.tsx Updated ownsObject method to handle guest users and added isOwner function.
apps/web/src/contexts/permissions.tsx Integrated ownsObject function for participant editing permissions.
apps/web/src/trpc/routers/polls.ts Updated logic for user identification to include guestId.
apps/web/src/trpc/routers/polls/comments.ts Modified comment creation logic to differentiate between guest and registered users.
apps/web/src/trpc/routers/polls/participants.ts Changed participant creation logic to conditionally assign guestId or userId.
apps/web/src/utils/permissions.ts Added new isOwner function to determine object ownership.
packages/database/prisma/migrations/* Created migration to add guest_id columns and indexes.
packages/database/prisma/schema.prisma Added guestId fields to Poll, Participant, and Comment models.

Possibly Related PRs

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


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 generate docstrings to generate docstrings for this PR. (Beta)
  • @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.

@vercel vercel bot temporarily deployed to Preview – landing December 24, 2024 12:22 Inactive
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: 0

🧹 Nitpick comments (4)
apps/web/src/contexts/permissions.tsx (1)

53-56: Consolidate repeated checks into ownsObject if possible
The additional check for context user IDs essentially duplicates ownsObject. Consider delegating all checks to ownsObject for more concise code.

apps/web/src/components/poll/desktop-poll.tsx (1)

311-311: Avoid confusion between userId and guestId.

Passing both userId and guestId to ParticipantRow is flexible but can be confusing. Consider clear naming or a single field that differentiates guests vs. registered users, if that simplifies usage.

apps/web/src/components/poll/desktop-poll/participant-row.tsx (1)

112-112: Simplify boolean expression

The ternary operator is unnecessary here since ownsObject() already returns a boolean.

-  const isYou = ownsObject(participant) ? true : false;
+  const isYou = ownsObject(participant);
🧰 Tools
🪛 Biome (1.9.4)

[error] 112-112: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

apps/web/src/components/discussion/discussion.tsx (1)

163-163: Consider paginating comments query

The comments query fetches all comments at once. For discussions with many comments, this could impact performance.

Consider implementing pagination or infinite scroll to improve performance for large discussions.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c79c0b7 and 210c368.

📒 Files selected for processing (12)
  • apps/web/src/app/[locale]/(admin)/polls/user-polls.tsx (1 hunks)
  • apps/web/src/components/discussion/discussion.tsx (2 hunks)
  • apps/web/src/components/poll/desktop-poll.tsx (1 hunks)
  • apps/web/src/components/poll/desktop-poll/participant-row.tsx (2 hunks)
  • apps/web/src/components/user-provider.tsx (3 hunks)
  • apps/web/src/contexts/permissions.tsx (2 hunks)
  • apps/web/src/trpc/routers/polls.ts (3 hunks)
  • apps/web/src/trpc/routers/polls/comments.ts (1 hunks)
  • apps/web/src/trpc/routers/polls/participants.ts (1 hunks)
  • apps/web/src/utils/permissions.ts (1 hunks)
  • packages/database/prisma/migrations/20241224103150_guest_id_column/migration.sql (1 hunks)
  • packages/database/prisma/schema.prisma (5 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
apps/web/src/components/poll/desktop-poll/participant-row.tsx

[error] 112-112: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

🔇 Additional comments (29)
apps/web/src/trpc/routers/polls.ts (3)

76-78: Consistent guest/user ID assignment [Approved]
This conditional spread operator correctly handles guest vs. registered user IDs.


99-105: Check null scenario for user field when guestId is present
When guestId is populated, the user field might be null. Ensure the frontend gracefully handles the possibility of poll.user being null.


175-177: Matches the guest/user logic in poll creation [Approved]
The same conditional ID assignment is applied here, maintaining consistency.

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

1-10: Ownership logic is straightforward and clear [Approved]
This method robustly distinguishes users from guests, ensuring correct ownership checks.

apps/web/src/contexts/permissions.tsx (2)

29-29: Destructuring ownsObject from context
Pulling in ownsObject is a clean way to centralize ownership checks across the app.


48-50: Improved null check for participants
Returning false when participant is not found prevents potential runtime issues.

apps/web/src/components/user-provider.tsx (3)

12-12: Importing isOwner
Importing isOwner ensures a single authority for ownership checks, improving maintainability.


32-35: Expanding signature to include guestId
Accepting an optional guestId standardizes ownership checks for both guests and registered users.


108-109: Delegation to isOwner
Delegating ownership logic cleanly unifies the user context with the permission utilities.

apps/web/src/trpc/routers/polls/participants.ts (1)

98-98: Conditional ID assignment on participant creation [Approved]
Properly assigns either guestId or userId based on the user’s status, staying consistent with the rest of the PR.

apps/web/src/app/[locale]/(admin)/polls/user-polls.tsx (1)

185-189: Consider clarifying how the user vs. guest fields are handled.

Allowing user to be null alongside an optional guestId provides flexibility for multiple user states. Ensure downstream usage consistently checks both fields so that logic remains clear when either is null.

packages/database/prisma/schema.prisma (6)

127-128: Ensure all references to userId handle nullable fields correctly.

Changing to String? allows polls without a registered user. Confirm that logic (in application code) properly covers cases where userId is now null, especially for existing references or constraints.


151-151: Check usage of the guest ID index.

The new guest ID index on Poll boosts query performance for guest users. Ensure queries that rely on the guest ID actually utilize this index.


189-189: Confirm participant creation for guests.

The optional guestId field in Participant allows storing guest data. Verify that participant creation logic properly sets guestId when dealing with guests, and ensure no collisions with userId.


200-200: Validate index usage on guestId in Participant.

This aligns with the Poll table’s approach. Double-check whether usage in TRPC resolvers or direct queries benefits from the new index.


248-248: Support guest-based comments in the application logic.

Adding guestId to Comment enables guest commenting. Ensure that conditional logic in comment creation/resolution consistently populates this field.


253-253: Leverage the new index on comment guestId.

This index should help performance when listing or filtering comments from guests. Confirm that relevant queries are in place.

packages/database/prisma/migrations/20241224103150_guest_id_column/migration.sql (9)

2-2: Added guest_id to comments.

This supports guest functionality but ensure references to this field in code are aligned with the new column.


5-5: Added guest_id to participants.

Allows distinguishing guests in participant records. Confirm your queries properly differentiate userId and guestId.


8-9: Polls table updated for guest usage.

Dropping NOT NULL from user_id and adding guest_id is a pivotal design change. Validate that existing poll logic gracefully handles possibly null user_id.


12-12: Index on comments_guest_id_idx.

Indexing guest_id on the comments table can enhance queries but verify the code patterns are indeed using this for filtering.


15-15: Index on participants_guest_id_idx.

Facilitates guest-based participant lookups. Confirm usage in TRPC or relevant controllers.


18-18: Index on polls_guest_id_idx.

Check that the actual queries filtering by guest_id in polls are present and optimized.


21-31: Poll migration logic for unknown user_id.

The migration sets guest_id to user_id if no matching user exists. Confirm that this fallback does not cause collisions or data integrity issues for existing user records.


33-45: Participants migration logic for unknown user_id.

Similar fallback approach ensures participants with invalid userId become guests. Confirm that subsequent code properly resolves them as guests and not partial users.


46-57: Comments migration logic and data consistency.

For comments referencing missing users, guest_id replaces user_id. Double-check that older references and user relationships are seamlessly replaced.

apps/web/src/trpc/routers/polls/comments.ts (1)

44-46: Ensure mutual exclusivity of userId and guestId

The conditional assignment looks correct but could be more explicit about the mutual exclusivity of these fields.

Let's verify the database schema and existing data:

✅ Verification successful

Mutual exclusivity of userId and guestId is properly enforced

Based on the Prisma schema and implementation:

  • The Comment model correctly defines userId and guestId as optional String fields with proper indexes
  • The comment creation logic in the router uses a spread operator to ensure only one of these fields is set based on ctx.user.isGuest
  • The schema doesn't enforce mutual exclusivity at the database level, but the application logic correctly handles this by using conditional assignment
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if any comments have both userId and guestId set
ast-grep --pattern 'model Comment {
  $$$
  userId String?
  guestId String?
  $$$
}'

# Check for potential data integrity issues
rg -A 5 'Comment.*create' 

Length of output: 540


Script:

#!/bin/bash
# Let's check the Prisma schema for Comment model constraints
fd 'schema.prisma' --exec cat {}

# Let's also check for any other Comment creation logic
rg -B 3 -A 3 'Comment.*create|createMany'

Length of output: 10902

apps/web/src/components/poll/desktop-poll/participant-row.tsx (1)

26-26: LGTM: Interface update for guest support

The addition of the optional guestId field to the participant interface correctly supports the guest user functionality.

apps/web/src/components/discussion/discussion.tsx (1)

203-203: LGTM: Proper permission handling

The permission check correctly handles both admin roles and object ownership, supporting the new guest user functionality.

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: 1

🧹 Nitpick comments (2)
apps/web/src/auth/merge-user.ts (2)

14-14: Consider using transactions if partial failures are a concern.
Setting guestId to null and assigning userId in multiple separate updateMany calls can lead to partial merges if any of these calls fail. Consider using a single transaction (prisma.$transaction) so that either all or none of the updates are committed.


26-26: Optional: Parallelize updates for performance.
All three updateMany calls are awaited sequentially. If these changes do not need to be applied in a strict order, consider running them in parallel using await Promise.all(...) to reduce the overall execution time.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 210c368 and 02c9673.

📒 Files selected for processing (1)
  • apps/web/src/auth/merge-user.ts (1 hunks)
🧰 Additional context used
📓 Learnings (1)
apps/web/src/auth/merge-user.ts (1)
Learnt from: lukevella
PR: lukevella/rallly#1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-11-12T09:08:14.221Z
Learning: The `mergeGuestsIntoUser()` function in `apps/web/src/utils/auth.ts` is correctly awaited.
🔇 Additional comments (3)
apps/web/src/auth/merge-user.ts (3)

9-11: Ensure guestIds list is properly validated.
Although this query filters rows by guestId, consider validating that guestIds is non-empty and contains valid entries before making the database call. This can help prevent unexpected updates or silent errors if the list is empty.


21-23: Maintain consistent logic for participants.
Merging participants by updating the guestId to null and assigning userId ensures a consistent approach across Poll, Participant, and Comment tables. It's good to see that the same pattern is followed here.


33-35: Confirm referencing correctness.
Double-check that guestIds aligns with how guest IDs are tracked in the comment table. If there's a mismatch in naming or foreign key references, this could potentially update unintended rows.

apps/web/src/auth/merge-user.ts Outdated Show resolved Hide resolved
@vercel vercel bot temporarily deployed to Preview – landing December 24, 2024 12:27 Inactive
@vercel vercel bot temporarily deployed to Preview – landing December 26, 2024 11:24 Inactive
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: 1

🧹 Nitpick comments (2)
apps/web/src/auth/merge-user.ts (2)

7-44: Good use of transactions for data consistency!

The implementation correctly uses a transaction to ensure atomic updates across multiple tables, with efficient parallel processing via Promise.all.

Consider adding error logging to track failed merges, as they could leave guest data in an inconsistent state:

 export const mergeGuestsIntoUser = async (
   userId: string,
   guestIds: string[],
 ) => {
+  console.log(`Merging guest IDs ${guestIds.join(', ')} into user ${userId}`);
   return await prisma.$transaction(async (tx) => {
     await Promise.all([
       // ... existing code ...
     ]);
+    console.log('Successfully merged guest accounts');
   });
 };

8-44: Consider adding retry logic for resilience.

While transactions provide atomicity, they might fail due to temporary database issues. For a more robust implementation, consider wrapping the operation in a retry mechanism.

Here's a suggested implementation using exponential backoff:

import { exponentialBackoff } from '@rallly/backend/utils';

export const mergeGuestsIntoUser = async (
  userId: string,
  guestIds: string[],
) => {
  return await exponentialBackoff(
    async () => {
      return await prisma.$transaction(async (tx) => {
        await Promise.all([
          // ... existing code ...
        ]);
      });
    },
    {
      maxAttempts: 3,
      initialDelay: 100,
    }
  );
};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 02c9673 and 515fa0c.

📒 Files selected for processing (4)
  • apps/web/src/app/[locale]/invite/[urlId]/invite-page.tsx (1 hunks)
  • apps/web/src/auth/merge-user.ts (1 hunks)
  • apps/web/src/contexts/permissions.tsx (2 hunks)
  • apps/web/src/trpc/routers/polls.ts (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/src/contexts/permissions.tsx
  • apps/web/src/trpc/routers/polls.ts
🧰 Additional context used
📓 Learnings (1)
apps/web/src/auth/merge-user.ts (1)
Learnt from: lukevella
PR: lukevella/rallly#1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-11-12T09:08:14.221Z
Learning: The `mergeGuestsIntoUser()` function in `apps/web/src/utils/auth.ts` is correctly awaited.
🔇 Additional comments (2)
apps/web/src/auth/merge-user.ts (1)

9-19: Verify the completeness of the merge operation.

The code updates three tables (polls, participants, comments), but there might be other tables or relations that need to be considered.

Let's check for other potential tables that might have guest references:

Also applies to: 21-31, 33-43

✅ Verification successful

Let me try a better search pattern to find table definitions.


The merge operation appears to be complete

Based on the schema.prisma file, the code correctly handles all tables that have a guestId column:

  • polls table
  • participants table
  • comments table

These are the only tables in the schema that contain guest references, and the merge operation in the code updates all of them. The other tables either don't have guest-related fields or are not relevant to the guest-to-user conversion process (like accounts, verification tokens, etc.).

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for table definitions that might contain guest_id
fd -e prisma$ | xargs rg -A 5 'model.*{' | rg -B 5 -A 10 'guest.*Id'

# Search for any other potential guest-related fields in the codebase
rg -g '!*.{log,lock}' -i 'guest.*id'

Length of output: 8233


Script:

#!/bin/bash
# Search for table definitions in schema.prisma
cat packages/database/prisma/schema.prisma

Length of output: 7995

apps/web/src/app/[locale]/invite/[urlId]/invite-page.tsx (1)

19-20: LGTM! Good refactoring of ownership check.

The change to use ownsObject centralizes the ownership logic in the useUser hook, making it more maintainable and consistent with the guest user support.

@vercel vercel bot temporarily deployed to Preview – landing December 26, 2024 11:37 Inactive
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: 0

🧹 Nitpick comments (1)
apps/web/src/trpc/routers/dashboard.ts (1)

17-18: Consider addressing the TODO comment about status enum.

The TODO comment suggests moving deleted status into an enum. This would indeed provide better type safety and make the status handling more maintainable.

Would you like me to help implement this improvement by:

  1. Creating an appropriate status enum that includes deleted/cancelled states
  2. Updating the schema and related code to use this enum
  3. Opening a GitHub issue to track this enhancement
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 515fa0c and 4f4e7f9.

📒 Files selected for processing (1)
  • apps/web/src/trpc/routers/dashboard.ts (1 hunks)
🔇 Additional comments (1)
apps/web/src/trpc/routers/dashboard.ts (1)

9-15: LGTM! Clean implementation of guest user filtering.

The conditional spread operator usage provides a clean way to switch between guestId and userId based on the user type. The implementation maintains mutual exclusivity between guest and registered users.

@lukevella lukevella merged commit 5b3c4ad into main Dec 27, 2024
9 checks passed
@lukevella lukevella deleted the guest-user-id branch December 27, 2024 10:12
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