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

Signup page backend #2832

Merged
merged 8 commits into from
Nov 13, 2024
Merged

Signup page backend #2832

merged 8 commits into from
Nov 13, 2024

Conversation

tomer-shvadron
Copy link
Collaborator

@tomer-shvadron tomer-shvadron commented Nov 12, 2024

  • feat: signup page backend
  • feat: small changes to enable token creation without enduser

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a CollectionFlowSignupController for handling user sign-up requests.
    • Added new endpoints for creating tokens and collection flow URLs in the WorkflowControllerExternal.
    • Implemented optional endUserId in various data models, enhancing flexibility in user associations.
    • Added a SignupDto for validating user sign-up data.
    • Introduced a new type ITokenScopeWithEndUserId to enhance token capabilities.
    • Added a new decorator for token authentication without requiring an end user.
  • Bug Fixes

    • Improved error handling in several methods to provide clearer feedback on issues.
  • Documentation

    • Updated Swagger API documentation to reflect new endpoints and response structures.
  • Tests

    • Added integration tests for the CollectionFlowSignupController to ensure proper functionality.

Copy link

changeset-bot bot commented Nov 12, 2024

⚠️ No Changeset found

Latest commit: 43778e3

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
Contributor

coderabbitai bot commented Nov 12, 2024

Walkthrough

This pull request introduces significant changes across multiple files in the workflows service. Key modifications include alterations to database constraints and model definitions to allow nullable relationships, enhancements to the WorkflowTokenRepository and WorkflowTokenService with new methods, and the introduction of a new controller for handling user sign-ups. Additionally, several guards and decorators are added to facilitate token management without requiring an end user, along with improvements to error handling and API documentation.

Changes

File Change Summary
services/workflows-service/prisma/migrations/.../migration.sql Drops and re-establishes the foreign key constraint on endUserId in WorkflowRuntimeDataToken, allowing null values.
services/workflows-service/prisma/schema.prisma Updates WorkflowRuntimeDataToken model to make endUserId and endUser nullable. Adds state and decisionAt fields to the Alert model.
services/workflows-service/src/auth/workflow-token/...repository.ts Renames prisma to prismaService, updates method signatures to use prismaService, and adds methods for finding and updating tokens.
services/workflows-service/src/auth/workflow-token/...service.ts Adds new methods for retrieving expired tokens and updating tokens in WorkflowTokenService.
services/workflows-service/src/collection-flow/...module.ts Introduces CollectionFlowSignupController to handle sign-up requests.
services/workflows-service/src/collection-flow/...service.ts Modifies syncWorkflow and uploadNewFile methods for improved logic and error handling.
services/workflows-service/src/collection-flow/...controller.ts Updates service references and modifies method signatures to enhance clarity and maintainability.
services/workflows-service/src/collection-flow/...end-user.controller.ts Changes getCompanyInfo method to use ITokenScopeWithEndUserId.
services/workflows-service/src/collection-flow/...files.controller.ts Removes logging and clarifies error handling in file upload.
services/workflows-service/src/collection-flow/dto/signup.dto.ts Introduces SignupDto for user sign-up data validation.
services/workflows-service/src/common/decorators/...decorator.ts Adds new type ITokenScopeWithEndUserId for enhanced token scope representation.
services/workflows-service/src/common/guards/...auth.decorator.ts Introduces UseTokenWithoutEnduserAuthGuard decorator for token-based authentication without end user.
services/workflows-service/src/common/guards/...auth.guard.ts Adds TokenWithoutEnduserAuthGuard for managing authorization based on tokens.
services/workflows-service/src/common/guards/...auth.module.ts Introduces TokenWithoutEnduserAuthModule to encapsulate related services and guards.
services/workflows-service/src/common/guards/...token-auth.guard.ts Updates TokenAuthGuard to enhance token validation logic.
services/workflows-service/src/workflow/dtos/...create-collection-flow-url.ts Changes endUserId property in CreateCollectionFlowUrlDto to optional.
services/workflows-service/src/workflow/...workflow.service.ts Modifies endUserId handling to allow null values and refines various methods for clarity and maintainability.
services/workflows-service/src/collection-flow/controllers/types.ts Introduces SignupConfig type for structured signup configuration.
services/workflows-service/src/end-user/end-user.repository.ts Renames prisma to prismaService and updates method implementations accordingly.
services/workflows-service/src/end-user/end-user.service.ts Adds optional transaction parameter to create method in EndUserService.
services/workflows-service/src/workflow/workflow.controller.external.ts Introduces new endpoints for creating tokens and collection flow URLs, updates method logic and error handling, and enhances Swagger documentation.
services/workflows-service/src/collection-flow/controllers/...test.ts Adds integration tests for CollectionFlowSignupController, verifying the sign-up process.
services/workflows-service/src/collection-flow/controllers/...signup.controller.ts Introduces CollectionFlowSignupController to handle user sign-up requests, including validation and error handling.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CollectionFlowSignupController
    participant EndUserService
    participant WorkflowTokenService

    User->>CollectionFlowSignupController: POST /signup
    CollectionFlowSignupController->>EndUserService: createEndUser(data)
    EndUserService-->>CollectionFlowSignupController: endUserId
    CollectionFlowSignupController->>WorkflowTokenService: updateToken(tokenScope, endUserId)
    WorkflowTokenService-->>CollectionFlowSignupController: success
    CollectionFlowSignupController-->>User: 201 Created
Loading

Possibly related PRs

Suggested reviewers

  • alonp99

Poem

🐰 In the burrow where the workflows flow,
Changes sprout, and new seeds grow.
Tokens dance, and sign-ups sing,
With every hop, new joys they bring!
So let us cheer, with ears held high,
For a brighter path, we now can fly! 🌼


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 9ae18c9 and 43778e3.

📒 Files selected for processing (2)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.signup.controller.ts (1 hunks)
  • services/workflows-service/src/collection-flow/controllers/types.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.signup.controller.ts
  • services/workflows-service/src/collection-flow/controllers/types.ts

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

🧹 Outside diff range and nitpick comments (12)
services/workflows-service/src/common/guards/token-guard-without-enduser/token-without-enduser-auth.decorator.ts (2)

6-7: Add JSDoc documentation for this security-critical decorator.

Since this decorator plays a crucial role in authentication, it should be well-documented with:

  • Purpose and usage
  • Security implications
  • Example usage

Add this documentation:

+/**
+ * Decorator that enables token-based authentication without requiring an end user,
+ * while explicitly disabling session-based authentication.
+ *
+ * @security This decorator should only be used for endpoints that specifically need
+ * to handle authentication without an end user context (e.g., initial signup flow).
+ *
+ * @example
+ * ```typescript
+ * @UseTokenWithoutEnduserAuthGuard()
+ * @Post('signup')
+ * async signup() {
+ *   // Handler implementation
+ * }
+ * ```
+ */
 export const UseTokenWithoutEnduserAuthGuard = () =>
   applyDecorators(UseGuards(TokenWithoutEnduserAuthGuard), disableSessionAuth());

6-7: Consider making the decorator more configurable.

The current implementation is rigid with no configuration options. Consider making it more flexible for different use cases.

Consider this enhancement:

-export const UseTokenWithoutEnduserAuthGuard = () =>
+export interface TokenAuthOptions {
+  throwOnMissingToken?: boolean;
+  allowExpiredTokens?: boolean;
+}
+
+export const UseTokenWithoutEnduserAuthGuard = (options?: TokenAuthOptions) =>
   applyDecorators(UseGuards(TokenWithoutEnduserAuthGuard), disableSessionAuth());
services/workflows-service/src/common/decorators/token-scope.decorator.ts (1)

Line range hint 11-15: Improve type safety in the TokenScope decorator

The decorator uses a type assertion (as ITokenScope) which bypasses TypeScript's type checking. Additionally, the return type isn't explicitly declared.

Consider this safer implementation:

-export const TokenScope = createParamDecorator((_, ctx: ExecutionContext) => {
+export const TokenScope = createParamDecorator<undefined, ExecutionContext, ITokenScope | null>((_, ctx: ExecutionContext): ITokenScope | null => {
   const request = ctx.switchToHttp().getRequest();
-  return (request.tokenScope as ITokenScope) || null;
+  const tokenScope = request.tokenScope;
+  return tokenScope && typeof tokenScope === 'object' ? tokenScope : null;
 });
services/workflows-service/src/collection-flow/dto/signup.dto.ts (2)

4-4: Add class-level API documentation.

Consider adding @ApiTags() and @ApiDescription() decorators to improve API documentation and provide more context about the signup DTO's purpose.

+@ApiTags('signup')
+@ApiDescription('Data transfer object for user signup information')
 export class SignupDto {

1-22: Consider additional security measures for signup process.

While the DTO provides good data validation, consider implementing these security measures at the controller/service level:

  1. Rate limiting for signup attempts
  2. CAPTCHA or similar anti-bot measures
  3. Email domain validation/blocklist
  4. Password complexity requirements (if applicable)

Would you like me to provide implementation examples for these security measures?

services/workflows-service/src/common/guards/token-guard-without-enduser/token-without-enduser-auth.module.ts (1)

1-11: Consider renaming for consistency with NestJS conventions.

The module name TokenWithoutEnduserAuthModule could be more concise. Consider renaming to TokenlessAuthModule or AnonymousTokenModule to better align with NestJS naming conventions while maintaining clarity of purpose.

-export class TokenWithoutEnduserAuthModule {}
+export class TokenlessAuthModule {}
services/workflows-service/src/collection-flow/controllers/collection-flow.end-user.controller.ts (1)

25-28: Consider enhancing error handling and type safety

The current implementation could benefit from:

  1. Explicit return type annotation
  2. Error handling for the service call
  3. Input validation beyond DTO

Consider applying these improvements:

   @common.Post()
   @swagger.ApiCreatedResponse({ type: [EndUserModel] })
-  getCompanyInfo(
+  async updateEndUserCompanyInfo(
     @TokenScope() tokenScope: ITokenScopeWithEndUserId,
     @common.Body() data: EndUserUpdateDto,
-  ) {
-    return this.endUserService.updateById(tokenScope.endUserId, { data: data });
+  ): Promise<EndUserModel> {
+    try {
+      return await this.endUserService.updateById(tokenScope.endUserId, { data });
+    } catch (error) {
+      throw new common.InternalServerErrorException('Failed to update end user company info');
+    }
   }
services/workflows-service/src/collection-flow/controllers/collection-flow.signup.ts (1)

15-20: Document the inheritance intention.

The use of protected visibility for injected services suggests this controller might be intended for inheritance. Consider adding a class-level JSDoc comment to explain this design decision, or change the visibility to private if inheritance is not intended.

+/**
+ * Collection flow signup controller.
+ * @description Uses protected members to allow inheritance by specialized controllers.
+ */
 @UseTokenWithoutEnduserAuthGuard()
 @ApiExcludeController()
services/workflows-service/src/collection-flow/collection-flow.service.ts (1)

231-234: LGTM! Consider enhancing error handling.

The conditional check aligns well with the PR objective of enabling token creation without end user. The change ensures that end user updates only occur when both the payload data and token scope contain valid end user information.

Consider adding error logging or debug information when the end user update is skipped, to help with troubleshooting:

    if (payload.data.endUser && tokenScope.endUserId) {
      const { ballerineEntityId: _, ...endUserData } = payload.data.endUser;
      await this.endUserService.updateById(tokenScope.endUserId, { data: endUserData });
+   } else if (payload.data.endUser) {
+     this.logger.debug('Skipping end user update: No endUserId in token scope', {
+       hasEndUserData: !!payload.data.endUser,
+       tokenScope: { endUserId: tokenScope.endUserId }
+     });
    }
services/workflows-service/src/common/guards/token-guard-without-enduser/token-without-enduser-auth.guard.ts (2)

32-32: Avoid using 'any' type when augmenting the request object

Casting req as any to add the tokenScope property bypasses TypeScript's type safety and can lead to maintenance issues.

Extend the Request interface to include the tokenScope property for better type safety:

interface TokenScopeRequest extends Request {
  tokenScope: typeof tokenEntity;
}

const req = context.switchToHttp().getRequest<TokenScopeRequest>();

// ...

req.tokenScope = tokenEntity;

14-14: Specify the return type for the 'canActivate' method

Explicitly defining the return type enhances code readability and type safety. The canActivate method should return Promise<boolean>.

Modify the method signature as follows:

-async canActivate(context: ExecutionContext) {
+async canActivate(context: ExecutionContext): Promise<boolean> {
services/workflows-service/src/common/guards/token-guard/token-auth.guard.ts (1)

22-22: Consider fetching only unexpired tokens

Currently, findByTokenWithExpiredUnscoped retrieves tokens regardless of their expiration status, and expiration is checked manually afterwards. For efficiency and security, consider using a method that fetches only unexpired tokens, such as findByToken, to minimize unnecessary processing of expired tokens.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a621cc5 and c7d3ade.

📒 Files selected for processing (18)
  • services/workflows-service/prisma/migrations/20241112125400_remove_enduser_constraint_from_token/migration.sql (1 hunks)
  • services/workflows-service/prisma/schema.prisma (2 hunks)
  • services/workflows-service/src/auth/workflow-token/workflow-token.repository.ts (2 hunks)
  • services/workflows-service/src/auth/workflow-token/workflow-token.service.ts (1 hunks)
  • services/workflows-service/src/collection-flow/collection-flow.module.ts (2 hunks)
  • services/workflows-service/src/collection-flow/collection-flow.service.ts (1 hunks)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.controller.ts (4 hunks)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.end-user.controller.ts (2 hunks)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.files.controller.ts (0 hunks)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.signup.ts (1 hunks)
  • services/workflows-service/src/collection-flow/dto/signup.dto.ts (1 hunks)
  • services/workflows-service/src/common/decorators/token-scope.decorator.ts (1 hunks)
  • services/workflows-service/src/common/guards/token-guard-without-enduser/token-without-enduser-auth.decorator.ts (1 hunks)
  • services/workflows-service/src/common/guards/token-guard-without-enduser/token-without-enduser-auth.guard.ts (1 hunks)
  • services/workflows-service/src/common/guards/token-guard-without-enduser/token-without-enduser-auth.module.ts (1 hunks)
  • services/workflows-service/src/common/guards/token-guard/token-auth.guard.ts (2 hunks)
  • services/workflows-service/src/workflow/dtos/create-collection-flow-url.ts (1 hunks)
  • services/workflows-service/src/workflow/workflow.service.ts (5 hunks)
💤 Files with no reviewable changes (1)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.files.controller.ts
✅ Files skipped from review due to trivial changes (1)
  • services/workflows-service/prisma/migrations/20241112125400_remove_enduser_constraint_from_token/migration.sql
🔇 Additional comments (26)
services/workflows-service/src/common/guards/token-guard-without-enduser/token-without-enduser-auth.decorator.ts (1)

1-7: Verify the security implications of combining token auth with disabled sessions.

The decorator combines token-based authentication with session disabling, which is a security-critical configuration. Please ensure this aligns with the intended authentication flow.

Let's verify the guard's implementation and usage:

✅ Verification successful

Security implications verified. No issues found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Analyze the guard implementation and its usage
# Expected results: 
# 1. Verify guard implements proper token validation
# 2. Identify routes using this decorator to ensure appropriate protection
# 3. Check for any session-related security implications

# Check guard implementation
echo "=== Guard Implementation ==="
ast-grep --pattern 'class TokenWithoutEnduserAuthGuard implements CanActivate {
  $$$
}'

# Find usages of this decorator
echo "=== Decorator Usage ==="
rg -l "UseTokenWithoutEnduserAuthGuard" 

# Check for session-related configurations
echo "=== Session Configurations ==="
rg -l "session" --type ts

Length of output: 11449

services/workflows-service/src/workflow/dtos/create-collection-flow-url.ts (2)

14-19: LGTM! Changes are well-implemented and consistent.

The modifications to make endUserId optional are implemented correctly with proper validation decorators and TypeScript types. This aligns well with the PR objective of enabling token creation without an end user.


14-19: Verify the impact on API consumers.

Since this is a breaking change in the API contract (making a previously required field optional), ensure that existing API consumers are aware of this change and can handle the optional endUserId.

services/workflows-service/src/common/guards/token-guard-without-enduser/token-without-enduser-auth.module.ts (1)

7-11: LGTM! Module structure follows NestJS best practices.

The module correctly provides and exports the necessary components for token authentication without end users.

services/workflows-service/src/collection-flow/controllers/collection-flow.end-user.controller.ts (2)

2-5: LGTM: Clean import restructuring

The import changes properly introduce the new token scope type while maintaining clean code organization.


25-28: Verify error handling in the service layer

Since this endpoint is part of the signup page backend implementation, we should ensure proper error handling exists in the service layer for cases like duplicate entries or validation failures.

services/workflows-service/src/auth/workflow-token/workflow-token.service.ts (1)

21-34: Verify repository implementation for null endUserId handling

These service methods support token management without end users, but we should verify the repository implementation.

services/workflows-service/src/auth/workflow-token/workflow-token.repository.ts (2)

56-66: ⚠️ Potential issue

Add validation constraints to prevent unrestricted updates.

The current implementation allows updating any field without validation. This could lead to security issues if not properly constrained at the service layer.

Consider applying these changes:

   async updateByToken(
     token: string,
-    data: Partial<Prisma.WorkflowRuntimeDataTokenUncheckedCreateInput>,
+    data: Pick<
+      Prisma.WorkflowRuntimeDataTokenUncheckedCreateInput,
+      'endUserId' | 'expiresAt'
+    >,
   ) {
     return await this.prisma.workflowRuntimeDataToken.update({
       where: {
         token,
+        deletedAt: null,
       },
       data,
     });
   }

This change:

  1. Restricts which fields can be updated using Pick
  2. Adds a soft-delete check to prevent updating deleted tokens

Let's verify the current usage to ensure these constraints won't break existing code:

#!/bin/bash
# Description: Check what fields are being updated through this method
# Expected: Find update operations to understand which fields need to be included in Pick

rg -A 5 'updateByToken' 

35-42: LGTM, but ensure proper handling of expired tokens.

The implementation correctly follows the repository pattern and maintains consistency with existing unscoped query methods. However, since this method can return expired tokens, ensure that the service layer properly validates the token expiration before performing sensitive operations.

Let's verify how this method is used in the service layer:

services/workflows-service/src/collection-flow/controllers/collection-flow.signup.ts (1)

1-14: LGTM! Imports and decorators are well structured.

The imports are organized properly, and the controller decorators appropriately handle authentication and API documentation exclusion.

services/workflows-service/src/collection-flow/collection-flow.module.ts (2)

42-42: LGTM! Clean import statement.

The import follows the existing pattern and is properly organized.


61-61: Verify required dependencies for signup functionality.

While the controller is properly added, let's verify that all necessary dependencies for the signup functionality are present in the module's providers.

services/workflows-service/src/collection-flow/controllers/collection-flow.controller.ts (4)

10-14: LGTM: Clean import organization

The imports are well-organized and the addition of ITokenScopeWithEndUserId type is properly structured.


30-31: LGTM: Improved dependency injection clarity

The reordering of dependencies and renaming to collectionFlowService improves code clarity and maintainability.


36-36: LGTM: Consistent service usage

The updates to use collectionFlowService are consistent across all methods and maintain the same functionality while being more explicit about the service being used.

Also applies to: 46-49, 72-72, 80-83, 89-89, 103-103, 108-108


40-41: Verify the impact of the type change

The parameter type change from ITokenScope to ITokenScopeWithEndUserId might affect existing clients of this endpoint. Please ensure all consumers of this endpoint are updated accordingly.

✅ Verification successful

Type Change Verified Successfully

The parameter type has been updated to ITokenScopeWithEndUserId with no remaining references to ITokenScope. Existing consumers, including apps/kyb-app/src/domains/collection-flow/collection-flow.api.ts, are compatible with this change.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any direct usage of this endpoint in the frontend code
rg -l "collection-flow/user" --type ts --type tsx

# Search for any references to the old type usage
rg "ITokenScope.*getUser" --type ts

Length of output: 115


Script:

#!/bin/bash
# Search for any direct usage of this endpoint in the frontend code
rg -l "collection-flow/user" --type=typescript --type=typescriptreact

# Search for any references to the old type usage
rg "ITokenScope.*getUser" --type=typescript

Length of output: 185


Script:

#!/bin/bash
# Search for any direct usage of this endpoint in the frontend code
rg -l "collection-flow/user" -g "*.ts" -g "*.tsx"

# Search for any references to the old type usage
rg "ITokenScope.*getUser" -g "*.ts" -g "*.tsx"

Length of output: 162

services/workflows-service/prisma/schema.prisma (2)

818-818: Consider data migration needs for new Alert state field

The addition of state and decisionAt fields to the Alert model is well-structured. However, since state is non-optional, existing alerts in the database will need to be migrated.

#!/bin/bash
# Check if there's a migration file for handling existing alerts

echo "Searching for migration file..."
fd "alert.*state" --type f ./prisma/migrations

# Check for potential default value in migration
echo "Checking migration content for default value..."
rg "ALTER.*Alert.*state.*DEFAULT" ./prisma/migrations

485-486: Verify handling of optional endUserId in existing code

The change to make endUserId optional aligns with the PR objective of enabling token creation without an end user. However, existing code might assume this field is always present.

services/workflows-service/src/common/guards/token-guard-without-enduser/token-without-enduser-auth.guard.ts (1)

28-30: Standardize error messages to prevent information disclosure

Providing specific error messages like 'Token has expired' can inadvertently expose sensitive information to potential attackers.

[security_issue]

Consider using a generic error message for all unauthorized access attempts:

if (tokenEntity.expiresAt < new Date()) {
-  throw new UnauthorizedException('Token has expired');
+  throw new UnauthorizedException('Unauthorized');
}
services/workflows-service/src/common/guards/token-guard/token-auth.guard.ts (1)

28-30: ⚠️ Potential issue

Potential conflict with token creation without an end user

The guard throws an UnauthorizedException when tokenEntity.endUserId is not set. Since one of the PR objectives is to allow token creation without the involvement of an end user, this check might prevent those tokens from functioning as intended. Please verify if this aligns with the desired behavior.

Ensure that tokens without an endUserId are handled appropriately throughout the application.

services/workflows-service/src/workflow/workflow.service.ts (6)

1522-1524: Initialization and retrieval of endUserId and entityData are appropriate

The initialization of endUserId to null and the use of optional chaining to safely access entityData ensure that the code handles cases where mainRepresentative might be undefined.


1530-1530: Proper null check for entityData before proceeding

The condition else if (entityData) correctly checks for the existence of entityData before using it, preventing potential runtime errors due to undefined values.


1547-1547: Consistent null safety with entityData

The use of if (entityData) continues to ensure that any operations on entityData are safe and won't result in null reference errors.


1558-1558: Correct handling of nullable endUserId in workflow token creation

Assigning endUserId: endUserId ?? null ensures compatibility with the updated schema where endUserId can be null. This change aligns with the modifications allowing tokens to be created without an associated end user.


1697-1697: ⚠️ Potential issue

Fix syntax error in function parameter definition

There's a syntax error in the function parameter definition at line 1697. In TypeScript, semicolons should not be used to separate parameters in a function. Replace the semicolon with a comma.

Apply this diff to fix the syntax error:

-private async __generateEndUserWithBusiness({
-  entityType,
-  workflowRuntimeData,
-  entityData: { firstName: string; lastName: string };
-  currentProjectId,
+private async __generateEndUserWithBusiness({
+  entityType,
+  workflowRuntimeData,
+  entityData: { firstName: string; lastName: string },
+  currentProjectId,

Likely invalid or redundant comment.


2087-2087: Confirm the correctness of the new logic introduced

The changes around line 2087 need to be reviewed to ensure they align with the intended functionality, especially concerning event handling and token creation without an end user.

Run the following script to search for any potential issues in the event handling logic:

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

🧹 Outside diff range and nitpick comments (3)
services/workflows-service/src/collection-flow/controllers/types.ts (1)

1-8: Add JSDoc documentation for the SignupConfig type

The type definition would benefit from documentation explaining its purpose, usage, and the implications of different configurations.

Add documentation like this:

+/**
+ * Configuration for the signup process.
+ * @property email.validation - When true, enables email validation during signup
+ * @example
+ * // Enable email validation
+ * const config: SignupConfig = { email: { validation: true } };
+ */
 export type SignupConfig =
   | {
       email?: {
         validation: boolean;
       };
     }
   | null
   | undefined;
services/workflows-service/src/collection-flow/dto/signup.dto.ts (1)

17-21: Consider security implications of validation messages.

While the email validation is functionally correct, consider using a generic error message for failed email validation to prevent potential user enumeration attacks. Specific validation errors could reveal whether an email address exists in your system.

   @ApiProperty({ required: true, type: String })
-  @IsEmail()
+  @IsEmail({}, {
+    message: 'Invalid credentials provided',
+  })
   @IsNotEmpty()
   @MaxLength(254)
   email!: string;
services/workflows-service/src/end-user/end-user.service.ts (1)

16-17: Consider adding JSDoc documentation for the transaction parameter

The transaction parameter addition is well-implemented and maintains backward compatibility. However, it would be beneficial to add documentation explaining when and why a transaction should be passed.

Add documentation like this:

+ /**
+  * Creates a new end user
+  * @param args - The end user creation parameters
+  * @param transaction - Optional transaction for atomic operations (e.g., when creating user during signup)
+  * @returns The created end user
+  */
async create(args: Parameters<EndUserRepository['create']>[0], transaction?: PrismaTransaction) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between c7d3ade and 7818943.

📒 Files selected for processing (9)
  • services/workflows-service/src/auth/workflow-token/workflow-token.repository.ts (3 hunks)
  • services/workflows-service/src/auth/workflow-token/workflow-token.service.ts (1 hunks)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.signup.ts (1 hunks)
  • services/workflows-service/src/collection-flow/controllers/types.ts (1 hunks)
  • services/workflows-service/src/collection-flow/dto/signup.dto.ts (1 hunks)
  • services/workflows-service/src/common/guards/token-guard-without-enduser/token-without-enduser-auth.guard.ts (1 hunks)
  • services/workflows-service/src/end-user/end-user.repository.ts (5 hunks)
  • services/workflows-service/src/end-user/end-user.service.ts (2 hunks)
  • services/workflows-service/src/workflow/workflow.controller.external.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • services/workflows-service/src/workflow/workflow.controller.external.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • services/workflows-service/src/auth/workflow-token/workflow-token.repository.ts
  • services/workflows-service/src/auth/workflow-token/workflow-token.service.ts
  • services/workflows-service/src/collection-flow/controllers/collection-flow.signup.ts
  • services/workflows-service/src/common/guards/token-guard-without-enduser/token-without-enduser-auth.guard.ts
🔇 Additional comments (10)
services/workflows-service/src/collection-flow/controllers/types.ts (1)

1-8: 🛠️ Refactor suggestion

Consider strengthening the type definition for better type safety

The current type definition has several potential issues:

  1. Allowing null/undefined makes it harder to handle the configuration safely
  2. Email validation being optional could lead to security gaps in the signup flow

Consider this stronger type definition:

-export type SignupConfig =
-  | {
-      email?: {
-        validation: boolean;
-      };
-    }
-  | null
-  | undefined;
+export type SignupConfig = {
+  email: {
+    validation: boolean;
+  };
+};

This change would:

  • Force explicit configuration of email validation
  • Remove the possibility of null/undefined configs
  • Require consumers to make conscious decisions about validation

Let's verify the impact of this change:

services/workflows-service/src/collection-flow/dto/signup.dto.ts (3)

1-4: LGTM! Clean and focused imports.

The imports are minimal and the class declaration follows proper naming conventions.


5-9: LGTM with previous suggestions.


11-15: LGTM with previous suggestions.

services/workflows-service/src/end-user/end-user.service.ts (1)

4-4: LGTM! Clean type import addition

The import is properly grouped with other type imports and aligns with the transaction handling enhancement.

services/workflows-service/src/end-user/end-user.repository.ts (5)

11-11: LGTM! Improved naming convention.

The rename from prisma to prismaService enhances code clarity by making the dependency's purpose more explicit.


17-19: LGTM! Proper transaction handling.

The create method correctly handles transactions and maintains type safety with proper generic constraints.


26-28: LGTM! Consistent service usage across find methods.

The find methods consistently use prismaService and properly implement project scoping.

Also applies to: 35-37, 45-52, 74-77, 92-100


Line range hint 83-88: LGTM! Proper transaction and type handling.

The update method correctly implements transaction support and maintains proper type safety with explicit return type.


Line range hint 60-66: Investigate and fix the type issue instead of using @ts-ignore.

The presence of @ts-ignore suggests a potential type mismatch that should be addressed properly rather than suppressed.

Let's investigate the type issue:

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

🧹 Outside diff range and nitpick comments (6)
services/workflows-service/src/collection-flow/controllers/collection-flow.signup.controller.intg.test.ts (4)

57-71: Consider adding type information for mocked services.

While the current mocking approach works, consider using TypeScript's Partial<Type> or jest's Mock<Type> for better type safety and IDE support. This would help catch potential interface changes during refactoring.

Example for one service:

-{ provide: AppLoggerService, useValue: noop },
+{ provide: AppLoggerService, useValue: noop as unknown as Partial<AppLoggerService> },

108-114: Consider extracting test data to constants.

Move hardcoded test values to constants at the top of the file for better maintainability and reusability.

const TEST_CUSTOMER = {
  name: 'signup-test-customer',
  displayName: 'Signup Test Customer',
  logoImageUri: 'test',
} as const;

136-138: Extract token expiration calculation to a helper function.

The date calculation logic could be reused in other tests. Consider moving it to a helper function.

const getTokenExpiryDate = (daysFromNow: number) => {
  const now = new Date();
  return new Date(now.setDate(now.getDate() + daysFromNow));
};

41-176: Consider architectural improvements for better test maintainability.

The test implementation could benefit from:

  1. Test Factory Pattern:

    • Create a factory class for generating test entities
    • Implement builder pattern for flexible test data creation
  2. Custom Helpers:

    • Add helper for token creation and management
    • Create shared assertions for common validations

This would make the tests more maintainable and easier to extend.

Example test factory:

class TestDataFactory {
  static createCustomer(override = {}) {
    return {
      name: 'signup-test-customer',
      displayName: 'Signup Test Customer',
      logoImageUri: 'test',
      ...override,
    };
  }

  static async createWorkflowToken(prisma: PrismaService, override = {}) {
    // Implementation
  }
}
services/workflows-service/src/collection-flow/controllers/collection-flow.signup.controller.ts (2)

27-27: Replace console.log statements with NestJS Logger service

Using console.log is not recommended for logging in production applications. Consider using the NestJS Logger service for better log management and to support different log levels.

Apply this diff to use the Logger service:

+import { Logger } from '@nestjs/common';

 export class CollectionFlowSignupController {
+  private readonly logger = new Logger(CollectionFlowSignupController.name);

   constructor(
     protected readonly prismaService: PrismaService,
     protected readonly endUserService: EndUserService,
     protected readonly workflowService: WorkflowService,
     protected readonly workflowTokenService: WorkflowTokenService,
   ) {}

   @common.Post()
   async signUp(@TokenScope() tokenScope: ITokenScope, @common.Body() payload: SignupDto) {
     try {
-      console.log('in signup');
+      this.logger.log('in signup');

       await this.prismaService.$transaction(async transaction => {
         const { config } = await this.workflowService.getWorkflowRuntimeDataById(
           tokenScope.workflowRuntimeDataId,
           {},
           [tokenScope.projectId],
         );

-        console.log('found workflow runtime');
+        this.logger.log('found workflow runtime');

         this.validateSignupInputByConfig(payload, config?.collectionFlow?.signup);

-        console.log('validated signup input');
+        this.logger.log('validated signup input');

         const endUser = await this.endUserService.create(
           {
             data: { ...payload, projectId: tokenScope.projectId },
           },
           transaction,
         );

-        console.log('created end user');
+        this.logger.log('created end user');

         await this.workflowTokenService.updateByToken(
           tokenScope.token,
           { endUserId: endUser.id },
           transaction,
         );

-        console.log('updated token');
+        this.logger.log('updated token');
       });
     } catch (error: unknown) {
-      console.log('error', error);
+      this.logger.error('Error in signUp method', error as Error);

       if (error instanceof common.BadRequestException) {
         throw error;
       }
       throw new common.InternalServerErrorException(error, 'Failed to process signup');
     }
   }

Also applies to: 35-35, 39-39, 48-48, 56-56, 59-59


82-85: Implement the isEmailValid function

The isEmailValid function currently always returns true, meaning no actual email validation is performed. Implement proper email validation to ensure the email addresses meet the required format.

Do you want me to provide an implementation for the email validation function or open a GitHub issue to track this task?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 7818943 and e01f630.

📒 Files selected for processing (4)
  • services/workflows-service/src/collection-flow/collection-flow.module.ts (2 hunks)
  • services/workflows-service/src/collection-flow/collection-flow.service.ts (2 hunks)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.signup.controller.intg.test.ts (1 hunks)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.signup.controller.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • services/workflows-service/src/collection-flow/collection-flow.module.ts
  • services/workflows-service/src/collection-flow/collection-flow.service.ts

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 (2)
services/workflows-service/src/collection-flow/controllers/collection-flow.signup.controller.ts (2)

27-32: Add explicit typing for the transaction parameter

The transaction parameter should be explicitly typed for better maintainability and type safety.

-      await this.prismaService.$transaction(async transaction => {
+      await this.prismaService.$transaction(async (transaction: Prisma.TransactionClient) => {

71-74: Implement email validation logic

The isEmailValid function currently returns true without any validation. This could allow invalid email addresses to pass through.

Would you like me to:

  1. Generate a proper email validation implementation using regex or a validation library?
  2. Create a GitHub issue to track this TODO?
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e01f630 and 2d3fa0e.

📒 Files selected for processing (1)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.signup.controller.ts (1 hunks)
🔇 Additional comments (2)
services/workflows-service/src/collection-flow/controllers/collection-flow.signup.controller.ts (2)

1-15: LGTM! Well-structured imports and appropriate decorators

The imports are well-organized and the decorators correctly implement the token-without-enduser requirement while properly hiding the controller from API documentation.


16-22: LGTM! Well-structured dependency injection

The constructor properly injects all required services with appropriate visibility modifiers.

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

🧹 Outside diff range and nitpick comments (3)
services/workflows-service/src/auth/workflow-token/workflow-token.repository.ts (3)

26-33: Document the purpose of "Unscoped" in the method name.

While the implementation looks correct, the term "Unscoped" in the method name needs clarification. Consider adding JSDoc comments to explain:

  1. What security or business rules this method bypasses
  2. When it's appropriate to use this unscoped version
+/**
+ * Finds a token without applying standard security scopes.
+ * @param token - The token to search for
+ * @returns The token if it exists, is not expired, and not deleted
+ */
 async findByTokenUnscoped(token: string) {

35-42: Document security implications of retrieving expired tokens.

While this method is useful for token management, please add documentation to:

  1. Explain the "Unscoped" suffix
  2. Clarify when it's safe to retrieve expired tokens
  3. Document potential security implications
+/**
+ * Retrieves a token regardless of its expiration status.
+ * @param token - The token to search for
+ * @returns The token if it exists and is not deleted
+ * @security This method bypasses expiration checks - use with caution
+ */
 async findByTokenWithExpiredUnscoped(token: string) {

Line range hint 44-54: Consider renaming method to reflect soft deletion behavior.

The current implementation has some inconsistencies:

  1. The method name suggests deletion but it performs a soft delete via update
  2. Unlike findByTokenWithExpiredUnscoped, this method won't handle expired tokens

Consider either:

  1. Renaming to softDeleteByTokenUnscoped for clarity
  2. Adding a separate method for handling expired tokens if needed
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 2d3fa0e and 9ae18c9.

📒 Files selected for processing (2)
  • services/workflows-service/src/auth/workflow-token/workflow-token.repository.ts (3 hunks)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.signup.controller.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.signup.controller.ts
🔇 Additional comments (2)
services/workflows-service/src/auth/workflow-token/workflow-token.repository.ts (2)

8-8: LGTM! Improved naming clarity.

The parameter rename from prisma to prismaService better reflects its role as a service dependency.


Line range hint 10-24: LGTM! Consistent parameter naming.

The method maintains type safety while properly handling token creation with project context.

@tomer-shvadron tomer-shvadron enabled auto-merge (squash) November 13, 2024 15:11
@tomer-shvadron tomer-shvadron merged commit d01f56b into dev Nov 13, 2024
10 checks passed
@tomer-shvadron tomer-shvadron deleted the bal-3039 branch November 13, 2024 15:13
@coderabbitai coderabbitai bot mentioned this pull request Nov 14, 2024
async findByTokenWithExpiredUnscoped(token: string) {
return await this.prismaService.workflowRuntimeDataToken.findFirst({
where: {
token,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since this table will queried based on 'token' field in order to get related context, we might want to add an index on top of this field

data: Parameters<typeof this.workflowTokenRepository.updateByToken>[1],
transaction?: PrismaTransaction,
) {
return await this.workflowTokenRepository.updateByToken(token, data, transaction);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since it’s important to avoid cross-tenant data exposure, we should enforce tenant isolation by ensuring that only end users related to the same projectId can connect. This helps prevent accidental data leakage across tenants.

Additionally, it’s preferable to use a single object parameter to encapsulate the data instead of passing a set of individual parameters.

async function updateWorkflowToken({ token, data, transaction })

Benefits:

  • It’s clear what each value represents since they are labeled within the object.
  • If new parameters are added, they can easily be added to the options object without changing the function signature, the refactor will be much easier.

Comment on lines +151 to +174
it('should create a new EndUser and attach it to the WorkflowRuntimeDataToken', async () => {
const signupDto = {
firstName: 'John',
lastName: 'Doe',
email: 'email@email.com',
};

expect(workflowRuntimeDataToken.endUserId).toBeNull();

const response = await request(app.getHttpServer())
.post('/collection-flow/signup')
.send(signupDto)
.set('authorization', `Bearer ${workflowRuntimeDataToken.token}`);

expect(response.status).toBe(201);

const workflowToken = await workflowTokenService.findByToken(workflowRuntimeDataToken.token);
expect(workflowToken?.endUserId).toBeDefined();

const endUser = await endUserRepository.findById(workflowToken?.endUserId ?? '', {}, [
project.id,
]);
expect(endUser).toBeDefined();
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

Create a test with 2 different end users and try to connect a non related end user, currently the test will pass...

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.

3 participants