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

Add login/registration forms #284

Merged
merged 3 commits into from
Feb 24, 2024
Merged

Add login/registration forms #284

merged 3 commits into from
Feb 24, 2024

Conversation

mohamedsalem401
Copy link
Contributor

@mohamedsalem401 mohamedsalem401 commented Feb 15, 2024

WebApp

Added login/registration pages for users. you might use this as a draft to implement login/register functionality.
You can also guide me through the changes you want to make.
I think the biggest breaking change was changing Prisma to allow a single user for every email

Update:

  • Now the login/registration flow works with Stytch.

Registration Page

Created a Registration Page which consists of two steps

  1. Register User
    image
  2. Create Organization (Optional)
    image

Login Page

Created Login Page
image

Code

State Management

created new sessionState which handle authed user and his access token

interface Session {
  user: User;
  accessToken: string;
}

interface SessionState {
  session: Session | null;
  setSession: (session: Session) => void;
}

const useSessionStore = create<SessionState>()((set) => ({
  session: null,
  setSession(session) {
    set({ session });
  },
}));

Hooks

Created new useLoginMutation and useRegisterMutation to handle user authentication

Api

Schema

modify users model by adding unique constraints to the user
image

Services

/auth/login

  1. Modify login service to return the user with the access token
return {
        user: rest,
        access_token: this.jwtService.sign(payload, {secret: process.env.JWT_SECRET})
}
  1. Modify login logic to add the ability to log in with email ( it was with id_user only )
    image

/auth/register

update create user constraints to throw an error if email already exists
image

Note

All new forms have client-side validation using react-hook-form and Zod.

Summary by CodeRabbit

  • New Features
    • Added authentication pages for registration and login with corresponding routes.
    • Introduced form components and validation schemas for user login, registration, and organization creation.
    • Implemented custom hooks for login and registration functionalities.
    • Integrated session management for user data and access tokens.
  • Bug Fixes
    • Enhanced error handling in login and registration processes to provide better user feedback.
  • Chores
    • Removed outdated relations and fields from the database schema to streamline the data model.
    • Added unique constraint to the email field in the users model to enforce email uniqueness.

@ghost
Copy link

ghost commented Feb 15, 2024

👇 Click on the image for a new way to code review

Review these changes using an interactive CodeSee Map

Legend

CodeSee Map legend

Copy link
Contributor

coderabbitai bot commented Feb 15, 2024

Walkthrough

The recent updates introduce comprehensive enhancements to the authentication and organization creation functionalities within a web application. Key improvements include the addition of login and registration pages with corresponding routes, form components with validation for user authentication and organization setup, and backend adjustments for user management. These changes streamline the user experience for registration and login processes, enforce data integrity through schema validations, and optimize session management with a new session store.

Changes

File Path Change Summary
apps/webapp/src/App.tsx Added routes for /auth/register and /auth/login.
apps/webapp/src/components/auth/.../login-schema.ts, .../register-schema.ts, .../create-organization-schema.ts Added Zod schemas for form validation.
.../login-user-form.tsx, .../register-user-form.tsx, .../create-organization-form.tsx Implemented form components with react-hook-form and Zod validation.
apps/webapp/src/hooks/mutations/... Added useLoginMutation and useRegisterMutation hooks for handling auth requests.
apps/webapp/src/routes/... Introduced RegisterPage and LoginPage components with layout and forms.
apps/webapp/src/state/sessionStore.ts Added a Zustand store for session management.
packages/api/prisma/schema.prisma, .../auth.service.ts Updated Prisma schema and auth service for improved user management and validation.

🐰✨

In the realm of code, where logic intertwines,
A rabbit hopped in, making changes so fine.
Auth flows now sleek, with forms so divine,
Users rejoice, for their experience shines.
🌟📝🔒

Through fields of data, validation takes flight,
Ensuring inputs are just perfectly right.
A leap towards progress, in the moonlight's glow,
CodeRabbit's work, making the web app flow.
🐾💻🚀

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>.
    • Generate unit-tests for this file.
  • 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 tests 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 generate interesting stats about this repository from git and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

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 as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • 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/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

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.

Review Status

Actionable comments generated: 6

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between ffd80d5 and 8ec5935.
Files ignored due to path filters (2)
  • apps/webapp/src/assets/login.jpeg is excluded by: !**/*.jpeg
  • apps/webapp/src/assets/register.jpeg is excluded by: !**/*.jpeg
Files selected for processing (15)
  • apps/webapp/src/App.tsx (2 hunks)
  • apps/webapp/src/components/auth/login/login-schema.ts (1 hunks)
  • apps/webapp/src/components/auth/login/login-user-form.tsx (1 hunks)
  • apps/webapp/src/components/auth/register/create-organization-form.tsx (1 hunks)
  • apps/webapp/src/components/auth/register/create-organization-schema.ts (1 hunks)
  • apps/webapp/src/components/auth/register/register-form.tsx (1 hunks)
  • apps/webapp/src/components/auth/register/register-schema.ts (1 hunks)
  • apps/webapp/src/components/auth/register/register-user-form.tsx (1 hunks)
  • apps/webapp/src/hooks/mutations/useLoginMutation.tsx (1 hunks)
  • apps/webapp/src/hooks/mutations/useRegisterMutations.tsx (1 hunks)
  • apps/webapp/src/routes/auth_.login.tsx (1 hunks)
  • apps/webapp/src/routes/auth_.register.tsx (1 hunks)
  • apps/webapp/src/state/sessionStore.ts (1 hunks)
  • packages/api/prisma/schema.prisma (4 hunks)
  • packages/api/src/@core/auth/auth.service.ts (4 hunks)
Additional comments: 10
apps/webapp/src/components/auth/login/login-schema.ts (1)
  • 4-7: Ensure that the registerSchema import and its pick method usage are correctly extracting only the email and password fields for the loginSchema. This approach is efficient for reusability but verify that registerSchema includes these fields and no additional unnecessary fields are being included.
apps/webapp/src/components/auth/register/register-form.tsx (1)
  • 6-11: The implementation of the registration form with a conditional rendering based on the registered state is straightforward and effective. However, ensure that there is a mechanism in place for handling errors during the registration process and providing feedback to the user.
apps/webapp/src/state/sessionStore.ts (1)
  • 22-32: The implementation of useSessionStore with Zustand and its persistence middleware is correctly set up for session management. Ensure that sensitive information, such as the accessToken, is securely handled and not exposed to the client-side unnecessarily.
apps/webapp/src/App.tsx (1)
  • 39-40: The addition of routes for /auth/register and /auth/login is correctly implemented, ensuring that users can navigate to the registration and login pages. This change aligns with the PR objectives to enhance user authentication and account management.
apps/webapp/src/components/auth/register/create-organization-form.tsx (1)
  • 33-33: The hardcoded stripe_customer_id in the mutation request is a placeholder. Ensure that this value is dynamically generated or obtained from the user's input or session if it's meant to represent a real Stripe customer ID.
apps/webapp/src/components/auth/login/login-user-form.tsx (1)
  • 13-89: The LoginUserForm component is well-structured and uses form validation effectively. Ensure that error messages from the login process are displayed to the user to improve the user experience.
apps/webapp/src/components/auth/register/register-user-form.tsx (1)
  • 14-121: The RegisterUserForm component correctly implements form handling and submission. Ensure that error handling and user feedback mechanisms are in place for both the registration and login processes.
packages/api/src/@core/auth/auth.service.ts (2)
  • 46-52: The check for an existing user by email before registration is a critical security measure to prevent duplicate accounts. This implementation correctly throws a BadRequestException if the email already exists.
  • 78-113: The login method's flexibility to allow login by id_user or email is a good feature. Ensure that the security of the login process is thoroughly tested, especially the password comparison and JWT token generation.
packages/api/prisma/schema.prisma (1)
  • 531-531: Adding a unique constraint to the email field in the users model is a good practice for ensuring data integrity and preventing duplicate accounts. This change supports the PR objectives related to enhancing user authentication and account management.

Comment on lines 3 to 5
export const organizationFormSchema = z.object({
name: z.string().min(1, 'Name is required'),
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider adding more validation rules to the name field in organizationFormSchema to ensure data integrity, such as a maximum length constraint.

-  name: z.string().min(1, 'Name is required'),
+  name: z.string().min(1, 'Name is required').max(100, 'Name must be less than 100 characters'),

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.

Suggested change
export const organizationFormSchema = z.object({
name: z.string().min(1, 'Name is required'),
});
export const organizationFormSchema = z.object({
name: z.string().min(1, 'Name is required').max(100, 'Name must be less than 100 characters'),
});

Comment on lines +3 to +8
export const registerSchema = z.object({
firstName: z.string().min(1, 'First name is required'),
lastName: z.string().min(1, 'Last name is required'),
email: z.string().min(1, 'Email is required').email('Email is invalid'),
password: z.string().min(8, 'Password must be at least 8 characters'),
});
Copy link
Contributor

Choose a reason for hiding this comment

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

The registerSchema includes basic validation for firstName, lastName, email, and password. Consider adding more comprehensive validation rules for email and password to enhance security, such as regex patterns for email format and password complexity requirements.

-  email: z.string().min(1, 'Email is required').email('Email is invalid'),
+  email: z.string().min(1, 'Email is required').email('Email is invalid').regex(/Your-Regex-Here/, 'Email format is invalid'),
-  password: z.string().min(8, 'Password must be at least 8 characters'),
+  password: z.string().min(8, 'Password must be at least 8 characters').regex(/Your-Password-Regex-Here/, 'Password format is invalid'),

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.

Suggested change
export const registerSchema = z.object({
firstName: z.string().min(1, 'First name is required'),
lastName: z.string().min(1, 'Last name is required'),
email: z.string().min(1, 'Email is required').email('Email is invalid'),
password: z.string().min(8, 'Password must be at least 8 characters'),
});
export const registerSchema = z.object({
firstName: z.string().min(1, 'First name is required'),
lastName: z.string().min(1, 'Last name is required'),
email: z.string().min(1, 'Email is required').email('Email is invalid').regex(/Your-Regex-Here/, 'Email format is invalid'),
password: z.string().min(8, 'Password must be at least 8 characters').regex(/Your-Password-Regex-Here/, 'Password format is invalid'),
});

Comment on lines 4 to 14
export default function RegisterPage() {
return (
<div className='min-h-screen grid lg:grid-cols-2 mx-auto text-left'>
<div className='flex-1 flex flex-col justify-center py-12 px-4 sm:px-6 lg:flex-none lg:px-20 xl:px-24'>
<RegisterForm />
</div>
<div className='hidden lg:block relative flex-1'>
<img className='absolute inset-0 h-full w-full object-cover' src={RegisterImage} alt='' />
</div>
</div>
);
Copy link
Contributor

Choose a reason for hiding this comment

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

The structure and layout of the RegisterPage are well-defined, ensuring a responsive design with the use of Tailwind CSS classes. Ensure that the alt attribute for the img tag in line 11 is filled with a descriptive text for accessibility purposes.

-  <img className='absolute inset-0 h-full w-full object-cover' src={RegisterImage} alt='' />
+  <img className='absolute inset-0 h-full w-full object-cover' src={RegisterImage} alt='Registration Page Background' />

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.

Suggested change
export default function RegisterPage() {
return (
<div className='min-h-screen grid lg:grid-cols-2 mx-auto text-left'>
<div className='flex-1 flex flex-col justify-center py-12 px-4 sm:px-6 lg:flex-none lg:px-20 xl:px-24'>
<RegisterForm />
</div>
<div className='hidden lg:block relative flex-1'>
<img className='absolute inset-0 h-full w-full object-cover' src={RegisterImage} alt='' />
</div>
</div>
);
export default function RegisterPage() {
return (
<div className='min-h-screen grid lg:grid-cols-2 mx-auto text-left'>
<div className='flex-1 flex flex-col justify-center py-12 px-4 sm:px-6 lg:flex-none lg:px-20 xl:px-24'>
<RegisterForm />
</div>
<div className='hidden lg:block relative flex-1'>
<img className='absolute inset-0 h-full w-full object-cover' src={RegisterImage} alt='Registration Page Background' />
</div>
</div>
);

Comment on lines 4 to 14
export default function LoginPage() {
return (
<div className='min-h-screen grid lg:grid-cols-2 mx-auto text-left'>
<div className='hidden lg:block relative flex-1'>
<img className='absolute inset-0 h-full w-full object-cover border-l' src={LoginImage} alt='login image' />
</div>
<div className='flex-1 flex flex-col justify-center py-12 px-4 sm:px-6 lg:flex-none lg:px-20 xl:px-24'>
<LoginUserForm />
</div>
</div>
);
Copy link
Contributor

Choose a reason for hiding this comment

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

The LoginPage implementation is consistent with the RegisterPage in terms of layout and responsive design. Similar to the previous comment, ensure the alt attribute for the img tag in line 8 is filled with descriptive text for accessibility.

-  <img className='absolute inset-0 h-full w-full object-cover border-l' src={LoginImage} alt='login image' />
+  <img className='absolute inset-0 h-full w-full object-cover border-l' src={LoginImage} alt='Login Page Background' />

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.

Suggested change
export default function LoginPage() {
return (
<div className='min-h-screen grid lg:grid-cols-2 mx-auto text-left'>
<div className='hidden lg:block relative flex-1'>
<img className='absolute inset-0 h-full w-full object-cover border-l' src={LoginImage} alt='login image' />
</div>
<div className='flex-1 flex flex-col justify-center py-12 px-4 sm:px-6 lg:flex-none lg:px-20 xl:px-24'>
<LoginUserForm />
</div>
</div>
);
export default function LoginPage() {
return (
<div className='min-h-screen grid lg:grid-cols-2 mx-auto text-left'>
<div className='hidden lg:block relative flex-1'>
<img className='absolute inset-0 h-full w-full object-cover border-l' src={LoginImage} alt='Login Page Background' />
</div>
<div className='flex-1 flex flex-col justify-center py-12 px-4 sm:px-6 lg:flex-none lg:px-20 xl:px-24'>
<LoginUserForm />
</div>
</div>
);

Comment on lines +13 to +14
password_hash: data.password,
}),
Copy link
Contributor

Choose a reason for hiding this comment

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

The password_hash field in the request body should be named password instead of password_hash to match the expected field in the backend and to avoid confusion, as hashing should be handled server-side.

-      password_hash: data.password,
+      password: data.password,

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.

Suggested change
password_hash: data.password,
}),
password: data.password,

method: 'POST',
body: JSON.stringify({
email: data.email,
password_hash: data.password,
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar to the previous comment in useRegisterMutations.tsx, the password_hash field in the request body should be named password for clarity and consistency.

-      password_hash: data.password,
+      password: data.password,

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.

Suggested change
password_hash: data.password,
password: data.password,

@naelob
Copy link
Contributor

naelob commented Feb 19, 2024

@mohamedsalem401 Thank you very much for everything you're doing since the start !
Its high quality and I wanted to highlight your really good work.

When it comes to this PR its impressive but we would like to user something like https://stytch.com/ in addition.
It would help everyone to connect also with google etc.
So the idea would be to extend what youve done with stytch, hence map even a google user inside our db (maybe the table users ?).

If you have ideas, welcome to hear them here !

Copy link

changeset-bot bot commented Feb 21, 2024

⚠️ No Changeset found

Latest commit: 2652b0a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

New and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/@types/[email protected] None +12 3.9 MB types
npm/[email protected] None +1 30.2 kB dougwilson
npm/[email protected] network Transitive: environment, unsafe +3 2.48 MB lgore-stytch

View full report↗︎

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.

Review Status

Actionable comments generated: 4

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 8ec5935 and 2652b0a.
Files ignored due to path filters (5)
  • apps/webapp/package.json is excluded by: !**/*.json
  • docker-compose.dev.yml is excluded by: !**/*.yml
  • packages/api/package.json is excluded by: !**/*.json
  • packages/api/swagger/swagger-spec.json is excluded by: !**/*.json
  • pnpm-lock.yaml is excluded by: !**/*.yaml
Files selected for processing (21)
  • .env.example (2 hunks)
  • apps/webapp/Dockerfile (1 hunks)
  • apps/webapp/Dockerfile.dev (1 hunks)
  • apps/webapp/src/App.tsx (2 hunks)
  • apps/webapp/src/components/auth/login/login-user-form.tsx (1 hunks)
  • apps/webapp/src/components/auth/register/create-organization-schema.ts (1 hunks)
  • apps/webapp/src/components/root-layout.tsx (2 hunks)
  • apps/webapp/src/hooks/mutations/useLoginMutation.tsx (1 hunks)
  • apps/webapp/src/main.tsx (2 hunks)
  • apps/webapp/src/routes/auth_.login.tsx (1 hunks)
  • apps/webapp/src/routes/auth_.register.tsx (1 hunks)
  • apps/webapp/src/utils/config.ts (1 hunks)
  • packages/api/scripts/init.sql (2 hunks)
  • packages/api/src/@core/auth/auth.controller.ts (2 hunks)
  • packages/api/src/@core/auth/auth.module.ts (2 hunks)
  • packages/api/src/@core/auth/auth.service.ts (4 hunks)
  • packages/api/src/@core/auth/guards/stytch.guard.ts (1 hunks)
  • packages/api/src/@core/auth/stytch/stytch.module.ts (1 hunks)
  • packages/api/src/@core/auth/stytch/stytch.service.ts (1 hunks)
  • packages/api/src/app.controller.ts (2 hunks)
  • packages/api/src/main.ts (2 hunks)
Files skipped from review as they are similar to previous changes (6)
  • apps/webapp/src/App.tsx
  • apps/webapp/src/components/auth/login/login-user-form.tsx
  • apps/webapp/src/components/auth/register/create-organization-schema.ts
  • apps/webapp/src/hooks/mutations/useLoginMutation.tsx
  • apps/webapp/src/routes/auth_.login.tsx
  • apps/webapp/src/routes/auth_.register.tsx
Additional comments: 16
packages/api/src/@core/auth/stytch/stytch.module.ts (1)
  • 1-9: The implementation of the StytchModule as a global module is correctly done, ensuring that StytchService can be easily injected and used across the application. Good job on structuring this module.
apps/webapp/src/utils/config.ts (1)
  • 7-7: The addition of STYTCH_TOKEN to the config object is correctly implemented, following the existing pattern for environment variable access. This ensures consistency in configuration management.
packages/api/src/@core/auth/stytch/stytch.service.ts (1)
  • 1-13: The implementation of StytchService is well-done, correctly extending StytchClient and utilizing ConfigService for accessing environment variables. This approach ensures secure and flexible configuration management.
apps/webapp/Dockerfile.dev (1)
  • 15-15: The addition of VITE_STYTCH_TOKEN as both an argument and an environment variable in the Dockerfile configuration is correctly done. This ensures that the application can access the Stytch token at runtime, aligning with best practices for Dockerfile configurations.

Also applies to: 19-19

apps/webapp/src/main.tsx (1)
  • 4-13: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [7-24]

The integration of Stytch authentication using StytchProvider and StytchHeadlessClient is correctly implemented. Configuring the client with STYTCH_TOKEN ensures secure and flexible management of the token. This is a solid approach to enhancing authentication in the application.

packages/api/src/@core/auth/guards/stytch.guard.ts (1)
  • 1-30: The implementation of StytchGuard for session validation using StytchService is well-done. It correctly follows NestJS best practices for creating custom guards and ensures secure session validation by throwing UnauthorizedException on authentication failure.
packages/api/src/@core/auth/auth.module.ts (1)
  • 25-25: The addition of StytchModule to the AuthModule's imports array is correctly done, ensuring that StytchService is available for authentication-related functionalities. This modular approach enhances the authentication capabilities of the application.
packages/api/src/app.controller.ts (1)
  • 36-41: The addition of the /stytch endpoint protected by StytchGuard is correctly implemented. Using @UseGuards to apply route protection and @ApiOperation for Swagger documentation demonstrates adherence to NestJS best practices for secure and well-documented APIs.
packages/api/src/main.ts (1)
  • 30-38: The addition of cookie-parser middleware and the configuration of CORS using FRONT_END_URL from ConfigService are correctly implemented. These changes enhance the application's security and flexibility in handling cookies and cross-origin requests, adhering to best practices.
apps/webapp/Dockerfile (1)
  • 31-31: The addition of VITE_STYTCH_TOKEN as both an argument and an environment variable in the Dockerfile is correctly done, mirroring the approach in Dockerfile.dev. This consistency ensures that the application can access the Stytch token at runtime across different environments.

Also applies to: 34-34

.env.example (1)
  • 16-18: The addition of STYTCH_PROJECT_ID, STYTCH_SECRET, FRONT_END_URL, and VITE_STYTCH_TOKEN to the .env.example file is correctly done. This documentation of required environment variables is essential for clear and effective application setup, ensuring that all necessary configurations for Stytch integration and frontend URLs are well-documented.

Also applies to: 58-58

apps/webapp/src/components/root-layout.tsx (1)
  • 5-10: > 📝 NOTE

This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [1-1]

Assuming the Toaster component was unused or replaced, its removal contributes to maintaining a clean and efficient codebase. It's good practice to remove unused imports and components.

packages/api/src/@core/auth/auth.service.ts (3)
  • 48-67: The modifications to the register method to integrate with Stytch and check for existing emails are correctly implemented. However, ensure that the handling of user data, especially sensitive information, aligns with security best practices.
  • 91-126: The modifications to the login method to support login by id_user or email and improve error handling are correctly done. This enhances the flexibility and robustness of the authentication process.
  • 136-145: The addition of the validateStytchToken method for Stytch token validation is correctly implemented, enhancing the service's capabilities to support modern authentication flows.
packages/api/scripts/init.sql (1)
  • 236-236: Making the email column in the users table UNIQUE is a good practice to enforce the uniqueness of user emails, which is essential for authentication systems. This change helps prevent duplicate accounts and supports the integrity of the login process. Ensure that the application logic gracefully handles cases where a user attempts to register with an email that already exists in the system, providing a clear and user-friendly error message.

Comment on lines +235 to +236
id_user text NOT NULL,
email text UNIQUE NOT NULL,
Copy link
Contributor

Choose a reason for hiding this comment

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

The change from uuid to text for the id_user column in both the users and api_keys tables may have implications for data integrity and performance. UUIDs are generally preferred for their uniqueness across databases without additional context. If the change to text is intended to accommodate a specific format or external system integration, ensure that there are mechanisms in place (e.g., application logic or database triggers) to enforce the uniqueness and format of these text-based identifiers.

@@ -895,7 +895,7 @@
api_key_hash text NOT NULL,
name text NULL,
id_project uuid NOT NULL,
id_user uuid NOT NULL,
id_user text NOT NULL,
Copy link
Contributor

Choose a reason for hiding this comment

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

The change in the id_user column data type in the api_keys table to text should be carefully considered for the same reasons mentioned for the users table. Additionally, ensure that the foreign key constraint (CONSTRAINT FK_8 FOREIGN KEY (id_user) REFERENCES users (id_user)) is correctly updated to reflect this change in data type. This is crucial for maintaining referential integrity between the api_keys and users tables.

Comment on lines +73 to +85
@Get('/callback')
async callback(@Query() query: { token: string }, @Res() res: Response) {
const user = await this.authService.validateStytchToken(query.token);

await this.authService.createUser({
email: user.emails[0].email,
first_name: user.name.first_name,
last_name: user.name.last_name,
password_hash: '',
});

//TODO make it dynamic
res.redirect('http://localhost/callback/?token=' + query.token);
Copy link
Contributor

Choose a reason for hiding this comment

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

The implementation of the callback method to handle Stytch token validation and redirection is correctly done. However, consider making the redirect URL (http://localhost/callback/) configurable to support different environments more flexibly.

- res.redirect('http://localhost/callback/?token=' + query.token);
+ const redirectUrl = this.configService.get('FRONT_END_CALLBACK_URL');
+ res.redirect(`${redirectUrl}/?token=${query.token}`);

Ensure ConfigService is injected and used to retrieve the FRONT_END_CALLBACK_URL from the environment configuration.


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.

Suggested change
@Get('/callback')
async callback(@Query() query: { token: string }, @Res() res: Response) {
const user = await this.authService.validateStytchToken(query.token);
await this.authService.createUser({
email: user.emails[0].email,
first_name: user.name.first_name,
last_name: user.name.last_name,
password_hash: '',
});
//TODO make it dynamic
res.redirect('http://localhost/callback/?token=' + query.token);
@Get('/callback')
async callback(@Query() query: { token: string }, @Res() res: Response) {
const user = await this.authService.validateStytchToken(query.token);
await this.authService.createUser({
email: user.emails[0].email,
first_name: user.name.first_name,
last_name: user.name.last_name,
password_hash: '',
});
//TODO make it dynamic
const redirectUrl = this.configService.get('FRONT_END_CALLBACK_URL');
res.redirect(`${redirectUrl}/?token=${query.token}`);

Comment on lines +74 to +89
async createUser(user: CreateUserDto, id_user?: string) {
try {
const foundUser = await this.prisma.users.findUnique({
where: { id_user: user.id_user },
const salt = await bcrypt.genSalt();
const hashedPassword = await bcrypt.hash(user.password_hash, salt);

return await this.prisma.users.create({
data: {
...user,
id_user: id_user || uuidv4(),
password_hash: hashedPassword,
},
});
} catch (error) {
handleServiceError(error, this.logger);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The addition of the createUser method is well-implemented, facilitating user creation with flexibility for Stytch integration. Consider reviewing the handling of password_hash, especially for users authenticated through external services like Stytch, to ensure security best practices are followed.

@mohamedsalem401
Copy link
Contributor Author

@nael
Sorry for being late on the updates, I was busy doing other things (working on other projects/searching for a job) but I managed to update the code so that it works with Stytch.

Now you should register an account on Stytch and add the secrets/projectID to the .env file.

Let me know if you have any suggestions on how we can improve this (we can discuss this on Discord, but I sent a couple of messages on Discord, but I don't think you guys check it very often).

@naelob naelob merged commit 8373ec5 into panoratech:main Feb 24, 2024
6 of 9 checks passed
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.

2 participants