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

Feat/schema dates #94

Merged
merged 9 commits into from
Sep 27, 2024
Merged

Feat/schema dates #94

merged 9 commits into from
Sep 27, 2024

Conversation

godchiSymbionix
Copy link
Collaborator

@godchiSymbionix godchiSymbionix commented Sep 26, 2024

Added createdAt, updatedAt and deletedAt fields to all tables

Summary by CodeRabbit

  • New Features

    • Enhanced user authorization checks when activating short links to ensure only authorized users can perform this action.
    • Updated test cases to include user authorization scenarios, improving overall test coverage.
  • Bug Fixes

    • Adjusted test cases to reflect the inclusion of user properties in mock entities, ensuring accurate testing of functionality.
    • Added tests to verify that an AuthenticationError is thrown for unauthorized users attempting to activate a short link.
  • Chores

    • Minor formatting adjustments made across various files for consistency and readability.

Copy link

coderabbitai bot commented Sep 26, 2024

Walkthrough

The pull request implements user authorization checks in the activateSHLinksUseCase function, ensuring that only authorized users can activate short links. It introduces a new user property in the input data structure and modifies existing test cases to reflect these changes. Additionally, a consistent date handling mechanism is established across various test cases using a dateValue constant.

Changes

File Path Change Summary
src/usecases/shlinks/*.test.ts Introduced dateValue constant for consistent date handling in mockSHLinkEntity and related objects. Updated created_at, updated_at, and config_exp properties to use dateValue. Added user authorization checks in test cases.
src/usecases/shlinks/*.ts Modified activateSHLinksUseCase to include user authorization checks. Updated method signature to include a user parameter. Enhanced logic to throw AuthenticationError for unauthorized users.

Possibly related PRs

  • Feat/get shlink accesses #47: This PR involves user authentication checks in the deactivateSHLinksUseCase, which aligns with the main PR's updates to the activateSHLinksUseCase for user authorization.
  • Feat/shlink filters #80: This PR introduces filters based on the status of share links, which may relate to the user authorization context established in the main PR, as both involve managing share link states and user interactions.

Suggested reviewers

  • BMartinos
  • yassinedorbozgithub
  • jacob-khoza-symb
  • amalessid
  • godchiSymbionix

🐇 In the meadow where links do play,
Authorization hops in a brand new way.
With dateValue shining bright,
Our tests align, everything feels right.
A rabbit's cheer for the code we create,
Hopping through changes, oh, isn't it great! 🌼✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 3188f23 and d5c7157.

📒 Files selected for processing (2)
  • src/usecases/shlinks/activate-shlink.test.ts (4 hunks)
  • src/usecases/shlinks/activate-shlink.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/usecases/shlinks/activate-shlink.test.ts
  • src/usecases/shlinks/activate-shlink.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
Collaborator

@amalessid amalessid left a comment

Choose a reason for hiding this comment

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

Hello @godchiSymbionix,
You're using new Date('2024-01-01T00:00:00Z'), in several places, maybe it would be better to declare a variable for this one and then use it whenever needed.

Copy link

@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: 22

🧹 Outside diff range and nitpick comments (52)
src/entities/base-entity.ts (1)

3-4: Use consistent naming convention

The current naming convention for the new fields (created_at, updated_at) uses snake_case, which is inconsistent with TypeScript's typical camelCase convention. Consider updating the field names to maintain consistency with TypeScript best practices.

You could update the field names like this:

export class BaseEntity {
  id?: string;
- created_at?: Date;
- updated_at?: Date;
+ createdAt?: Date;
+ updatedAt?: Date;
}
src/mappers/access-ticket-mapper.ts (1)

5-13: LGTM! Consider adding a type for accessTicketEntity.

The changes to mapEntityToModel look good. The addition of created_at and updated_at fields aligns with the PR objective of adding timestamp fields to all tables. The explicit return type is a good practice for type safety.

Consider adding an explicit type annotation for the accessTicketEntity parameter to improve code readability and maintainability:

export const mapEntityToModel = (
  accessTicketEntity: AccessTicketEntity
): AccessTicketModel | undefined => {
  // ... rest of the function
}
src/domain/models/user.ts (1)

Line range hint 1-58: Consider adding getter and setter methods for new timestamp fields

To maintain consistency with the existing pattern in the class, consider adding getter and setter methods for the createdAt and updatedAt fields.

Here's a suggested implementation:

getCreatedAt(): Date | undefined {
  return this.createdAt;
}

setCreatedAt(createdAt: Date): void {
  this.createdAt = createdAt;
}

getUpdatedAt(): Date | undefined {
  return this.updatedAt;
}

setUpdatedAt(updatedAt: Date): void {
  this.updatedAt = updatedAt;
}

Add these methods to the class to provide a consistent interface for accessing and modifying the new timestamp fields.

src/domain/models/shlink-access.ts (3)

11-12: Good addition of timestamp fields, consider adding deletedAt

The addition of createdAt and updatedAt fields aligns well with the PR objectives. These optional Date parameters will allow for better tracking of record lifecycles.

Consider also adding a deletedAt parameter to fully implement the timestamp fields mentioned in the PR objectives:

  constructor(
    private shlinkId: string,
    private accessTime: Date,
    private recipient: string,
    private id?: string,
    createdAt?: Date,
    updatedAt?: Date,
+   deletedAt?: Date
  ) {

21-22: Correct usage of superclass constructor, consider adding deletedAt

The createdAt and updatedAt parameters are correctly passed to the superclass constructor.

If you add the deletedAt parameter as suggested earlier, make sure to pass it to the superclass constructor as well:

    super(
      z.object({
        shlinkId: z.string().min(1),
        id: z.string().optional(),
        access_time: z.date().default(new Date()),
        recipient: z.string().min(1)
      }),
      createdAt,
      updatedAt,
+     deletedAt
    );

Line range hint 1-58: Implement deletedAt field to fully meet PR objectives

The PR objectives mention adding three timestamp fields: createdAt, updatedAt, and deletedAt. While createdAt and updatedAt have been implemented, the deletedAt field is missing from the current implementation.

To fully meet the PR objectives and provide complete lifecycle tracking for records, please add the deletedAt field to the class. This involves:

  1. Adding it as an optional parameter to the constructor
  2. Passing it to the superclass constructor
  3. Including it in the validation schema
  4. Adding getter and setter methods for it

Here's a template for the getter and setter methods you can add:

getDeletedAt(): Date | undefined {
  return this.deletedAt;
}

setDeletedAt(deletedAt: Date): void {
  this.deletedAt = deletedAt;
}
src/mappers/user-mapper.ts (1)

Line range hint 1-50: Ensure consistency across all mapper functions

After reviewing all the mapper functions, there's a general lack of consistency in how the new timestamp fields (created_at and updated_at) are handled. To maintain data integrity and meet the PR objectives, ensure that these fields are consistently mapped across all functions: mapEntityToModel, mapModelToEntity, mapModelToDto, and mapDtoToModel.

Also, consider the following points:

  1. Update the UserModel, UserEntity, and UserDto interfaces/classes to include these new fields.
  2. Decide whether the deletedAt field mentioned in the PR objectives should be included in these mappers.
  3. Ensure that all places where these mapper functions are used are updated to handle the new fields correctly.
src/mappers/shlink-access-mapper.ts (4)

Line range hint 7-15: Consider adding timestamp fields to the entity mapping.

The PR objectives mention adding createdAt, updatedAt, and deletedAt fields to all tables. However, these fields are not included in the mapModelToEntity function. Consider updating the function to include these fields in the entity mapping.

Here's a suggested implementation:

export const mapModelToEntity = (
  shlinkAccessModel?: SHLinkAccessModel,
): SHLinkAccessEntity | undefined => {
  return shlinkAccessModel
    ? {
        access_time: shlinkAccessModel.getAccessTime(),
        recipient: shlinkAccessModel.getRecipient(),
        shlink_id: shlinkAccessModel.getSHLinkId(),
        id: shlinkAccessModel.getId(),
+       created_at: shlinkAccessModel.getCreatedAt(),
+       updated_at: shlinkAccessModel.getUpdatedAt(),
+       deleted_at: shlinkAccessModel.getDeletedAt(),
      }
    : undefined;
};

Note: Ensure that the corresponding getter methods are added to the SHLinkAccessModel class if they don't already exist.


Line range hint 20-29: Consider adding the deleted_at field and updating the model constructor.

While created_at and updated_at have been added, the deleted_at field mentioned in the PR objectives is still missing. Additionally, ensure that the SHLinkAccessModel constructor is updated to accept these new parameters.

Here's a suggested implementation:

export const mapEntityToModel = (
  shlinkAccessEntity?: SHLinkAccessEntity,
): SHLinkAccessModel | undefined => {
  return shlinkAccessEntity
    ? new SHLinkAccessModel(
        shlinkAccessEntity.shlink_id,
        shlinkAccessEntity.access_time,
        shlinkAccessEntity.recipient,
        shlinkAccessEntity.id,
        shlinkAccessEntity.created_at,
        shlinkAccessEntity.updated_at,
+       shlinkAccessEntity.deleted_at,
      )
    : undefined;
};

Also, ensure that the SHLinkAccessModel constructor in the model file is updated to accept these new parameters:

constructor(
  shlinkId: string,
  accessTime: Date,
  recipient: string,
  id: string,
  createdAt: Date,
  updatedAt: Date,
  deletedAt: Date | null
) {
  // ... constructor implementation
}

Line range hint 34-43: Consider adding timestamp fields to the DTO mapping.

The PR objectives mention adding createdAt, updatedAt, and deletedAt fields to all tables. However, these fields are not included in the mapModelToDto function. Consider updating the function to include these fields in the DTO mapping.

Here's a suggested implementation:

export const mapModelToDto = (
  shlinkAccessModel?: SHLinkAccessModel,
): SHLinkAccessDto | undefined => {
  return shlinkAccessModel
    ? {
        id: shlinkAccessModel.getId(),
        shlinkId: shlinkAccessModel.getSHLinkId(),
        accessTime: shlinkAccessModel.getAccessTime(),
        recipient: shlinkAccessModel.getRecipient(),
+       createdAt: shlinkAccessModel.getCreatedAt(),
+       updatedAt: shlinkAccessModel.getUpdatedAt(),
+       deletedAt: shlinkAccessModel.getDeletedAt(),
      }
    : undefined;
};

Note: Ensure that the corresponding getter methods are added to the SHLinkAccessModel class and that the SHLinkAccessDto interface is updated to include these new fields.


Line range hint 1-44: Summary: Ensure consistent implementation of timestamp fields across all mappings

While the changes in this file are a step in the right direction, there are a few inconsistencies and potential improvements to fully align with the PR objectives:

  1. The mapModelToEntity function needs to be updated to include all three timestamp fields (createdAt, updatedAt, deletedAt).
  2. The mapEntityToModel function should include the deleted_at field.
  3. The mapModelToDto function needs to be updated to include all three timestamp fields.

Additionally, please ensure that the following related changes are made:

  1. Update the SHLinkAccessModel class to include getter and setter methods for the new timestamp fields.
  2. Update the SHLinkAccessDto interface to include the new timestamp fields.
  3. Verify that the SHLinkAccessEntity type definition includes the new timestamp fields.

These changes will ensure consistency across the entire mapping process and fully implement the PR objectives.

src/infrastructure/repositories/prisma/base-repository.ts (1)

Issues Found with createdAt and deletedAt Handling

The repository methods do not handle the createdAt and deletedAt fields as required by the PR objectives:

  • insert and insertMany Methods: Do not explicitly set the createdAt field.
  • delete Method: Does not implement soft deletes using the deletedAt field.
🔗 Analysis chain

Line range hint 1-63: Verify handling of createdAt and deletedAt fields

The PR objectives mention adding createdAt, updatedAt, and deletedAt fields to all tables. While we've addressed the updatedAt (or updated_at) field in the update method, it's important to ensure that the createdAt and deletedAt fields are also properly handled in the repository methods.

Please verify the following:

  1. Ensure that the insert and insertMany methods correctly handle the createdAt field. If Prisma doesn't set this automatically, you may need to explicitly set it.

  2. Consider implementing soft deletes using the deletedAt field in the delete method, if that's part of the intended functionality.

Run the following script to check the current implementation:

Based on the results, you may need to update these methods to ensure proper handling of the new timestamp fields.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the handling of createdAt and deletedAt fields in the repository methods

# Test: Search for createdAt handling in insert methods
echo "Checking createdAt handling in insert methods:"
rg --type typescript -A 5 'async insert' src/infrastructure/repositories
rg --type typescript -A 5 'async insertMany' src/infrastructure/repositories

# Test: Search for deletedAt handling in delete method
echo "Checking deletedAt handling in delete method:"
rg --type typescript -A 5 'async delete' src/infrastructure/repositories

Length of output: 537


Script:

#!/bin/bash
# Description: Check the handling of createdAt and deletedAt fields in the repository methods

# Test: Search for createdAt handling in insert methods
echo "Checking createdAt handling in insert methods:"
rg --glob "*.ts" -A 5 'async insert' src/infrastructure/repositories
rg --glob "*.ts" -A 5 'async insertMany' src/infrastructure/repositories

# Test: Search for deletedAt handling in delete method
echo "Checking deletedAt handling in delete method:"
rg --glob "*.ts" -A 5 'async delete' src/infrastructure/repositories

Length of output: 2309

src/domain/dtos/shlink-endpoint.ts (2)

50-50: Approved: Improved example for urlPath

The updated example for urlPath provides a clearer representation of the expected value. This change enhances the documentation and helps developers understand the purpose of this property better.

Consider adding a brief explanation of what /summary represents in the context of a share link endpoint. For example:

 *           type: string
 *           description: An optional string representing the share link endpoint's query parameters.
-*           example: /summary
+*           description: An optional string representing the share link endpoint's path or view.
+*           example: /summary  # Represents a summary view of the share link

Missing Timestamp Fields in DTO Classes

The PR objectives mention adding timestamp fields (createdAt, updatedAt, deletedAt) to all DTOs. However, the following DTO classes in src/domain/dtos/shlink-endpoint.ts are missing these fields:

  • CreateSHLinkEndpointDto
  • SHLinkEndpointDto

Please ensure that all DTO classes include the necessary timestamp fields as per the PR objectives.

🔗 Analysis chain

Line range hint 1-54: Verify: Discrepancy between PR objectives and implemented changes

The PR objectives mention adding timestamp fields (createdAt, updatedAt, deletedAt) to all tables. However, these changes are not reflected in the current file. Could you please clarify:

  1. Are these timestamp fields implemented in other files not provided for this review?
  2. If not, are these changes still planned to be implemented as part of this PR?
  3. If the objectives have changed, could you update the PR description to reflect the current goals?

To help verify the implementation of timestamp fields across the project, you can run the following script:

This will help us understand if the timestamp fields have been implemented in other parts of the project.



</details>

<details>
<summary>🏁 Scripts executed</summary>

The following scripts were executed for the analysis:

Script:

```shell
#!/bin/bash
# Description: Search for timestamp fields in DTO and entity files

# Search for createdAt, updatedAt, and deletedAt in TS files
echo "Searching for timestamp fields in DTO and entity files:"
rg --type typescript -e 'createdAt|updatedAt|deletedAt' src/

Length of output: 218


Script:

#!/bin/bash
# Description: Search for timestamp fields in DTO and entity files

# Corrected search for createdAt, updatedAt, and deletedAt in TypeScript files
echo "Searching for timestamp fields in DTO and entity files:"
rg --type ts -e 'createdAt|updatedAt|deletedAt' src/

Length of output: 5106

src/mappers/shlink-endpoint-mapper.ts (1)

Line range hint 1-57: Ensure consistent implementation of timestamp fields across all mapping functions.

The changes in this file partially implement the PR objectives by adding created_at and updated_at fields to the mapEntityToModel function. However, there are inconsistencies in the implementation across different mapping functions:

  1. mapEntityToModel: Includes created_at and updated_at, but missing deletedAt.
  2. mapModelToEntity: Doesn't include any of the new timestamp fields.
  3. mapModelToDto: Doesn't include any of the new timestamp fields.
  4. mapDtoToModel: Doesn't include any of the new timestamp fields.

To fully align with the PR objectives and maintain consistency:

  1. Implement createdAt, updatedAt, and deletedAt fields in all mapping functions.
  2. Ensure that the corresponding model, entity, and DTO interfaces/classes are updated to include these new fields.
  3. Verify that the naming convention for these fields is consistent across all usages (e.g., created_at vs createdAt).

Consider creating a base interface or type for the timestamp fields to ensure consistency across all entities and reduce code duplication. For example:

interface TimeStampedFields {
  createdAt: Date;
  updatedAt: Date;
  deletedAt?: Date;
}

interface SHLinkEndpointBase extends TimeStampedFields {
  id: string;
  shlinkId: string;
  serverConfigId: string;
  urlPath: string;
}

type SHLinkEndpointEntity = SHLinkEndpointBase;
type SHLinkEndpointDto = SHLinkEndpointBase;

This approach would help maintain consistency and make it easier to add these fields to new entities in the future.

src/mappers/access-ticket-mapper.test.ts (3)

6-7: Consider using a more appropriate date for testing.

The dateValue constant is set to a future date (2024). For testing purposes, it's generally better to use a known past date or the current date to avoid potential issues with future dates.

Consider modifying the date to a past or current date:

-const dateValue = new Date('2024-01-01T00:00:00Z')
+const dateValue = new Date('2023-01-01T00:00:00Z') // or use new Date() for the current date

14-15: LGTM! Minor formatting suggestion.

The addition of created_at and updated_at properties aligns well with the PR objectives. Good job on using the dateValue constant for consistency.

Consider adding spaces after the colons for better readability:

-        created_at:dateValue,
-        updated_at:dateValue
+        created_at: dateValue,
+        updated_at: dateValue

Line range hint 37-49: Update mapModelToEntity test to include new timestamp fields.

While the AccessTicketEntity has been updated with created_at and updated_at fields, the test case for mapModelToEntity doesn't reflect these changes. To ensure complete test coverage, consider updating this test case as well.

Here's a suggested update to the test case:

it('should map a valid AccessTicketModel to AccessTicketEntity', () => {
  const model = new AccessTicketModel('abc', '123');
  model.setCreatedAt(dateValue);
  model.setUpdatedAt(dateValue);

  const entity = mapModelToEntity(model);

  expect(entity).toEqual({
    id: '123',
    shlink_id: 'abc',
    created_at: dateValue,
    updated_at: dateValue
  });
});

Note: This assumes that AccessTicketModel has been updated with methods to set and get the new timestamp fields. If not, you may need to update the AccessTicketModel class as well.

src/usecases/shlink-qrcode/get-shlink-qrcode.test.ts (2)

22-25: LGTM! Consider enhancing test coverage for new fields.

The addition of createdAt, updatedAt, and deletedAt fields to the mockSHLink object aligns well with the PR objectives. The use of a specific date for testing and setting deletedAt to null are appropriate choices.

To ensure comprehensive test coverage, consider adding assertions to verify these new fields in your test cases. For example:

it('should include the new timestamp fields in the encoded SHLink', async () => {
  // ... existing test setup ...

  expect(encodeSHLink).toHaveBeenCalledWith(expect.objectContaining({
    createdAt: expect.any(Date),
    updatedAt: expect.any(Date),
    deletedAt: null
  }));

  // ... rest of the test ...
});

This addition would validate that the new fields are correctly passed to the encodeSHLink function, ensuring they are included in the QR code generation process.


Line range hint 31-67: Enhance test coverage for new timestamp fields

While the changes to mockSHLink are correct, the current test cases don't explicitly verify how these new fields affect the QR code generation process. To ensure comprehensive coverage, consider the following enhancements:

  1. Modify the existing tests to assert that the new fields are included in the encoded data.
  2. Add a new test case that specifically checks the handling of different deletedAt values (null vs. date).

Here's an example of how you could enhance the first test case:

it('should return an image buffer when QR code generation is successful', async () => {
  // ... existing test setup ...

  const result = await getSHLinkQRCodeUseCase(mockSHLink);

  expect(encodeSHLink).toHaveBeenCalledWith(expect.objectContaining({
    createdAt: expect.any(Date),
    updatedAt: expect.any(Date),
    deletedAt: null
  }));

  // ... rest of the test ...
});

And add a new test case:

it('should handle different deletedAt values correctly', async () => {
  const deletedSHLink = { ...mockSHLink, deletedAt: new Date('2024-02-01T00:00:00Z') };
  
  await getSHLinkQRCodeUseCase(deletedSHLink);

  expect(encodeSHLink).toHaveBeenCalledWith(expect.objectContaining({
    deletedAt: expect.any(Date)
  }));

  // You might want to add more assertions here to verify the QR code content
});

These changes will help ensure that the new timestamp fields are correctly handled throughout the QR code generation process.

src/domain/models/shlink.ts (1)

15-16: LGTM! Consider adding default values for timestamps.

The addition of createdAt and updatedAt parameters aligns well with the PR objectives. The optional nature and Date type are appropriate for these fields.

Consider setting default values for these fields in the constructor to ensure they are always populated:

createdAt: Date = new Date(),
updatedAt: Date = new Date()

This would automatically set the current timestamp when a new instance is created, which is a common practice for such fields.

src/domain/models/server-config.ts (2)

36-39: Add type validation for new timestamp fields.

The inclusion of createdAt and updatedAt in the schema is correct. However, consider adding type validation for these new fields to ensure data integrity.

Consider updating the schema to include type validation:

 refreshToken: z.string().optional().nullable(),
+createdAt: z.date().optional().nullable(),
+updatedAt: z.date().optional().nullable()
 }),
 createdAt,
 updatedAt

This change will ensure that the createdAt and updatedAt fields are properly validated as optional Date objects.


Line range hint 1-114: Consider additional improvements to fully meet PR objectives.

While the addition of createdAt and updatedAt fields is a good start, there are a few points to consider for improvement:

  1. Add getter and setter methods for createdAt and updatedAt to maintain consistency with other fields in the class.
  2. Implement the deletedAt field, which was mentioned in the PR objectives but is currently missing from this implementation.

Here's a suggestion for adding getter and setter methods:

getCreatedAt(): Date | undefined {
  return this.createdAt;
}

setCreatedAt(createdAt: Date): void {
  this.createdAt = createdAt;
}

getUpdatedAt(): Date | undefined {
  return this.updatedAt;
}

setUpdatedAt(updatedAt: Date): void {
  this.updatedAt = updatedAt;
}

Don't forget to implement the deletedAt field similarly to createdAt and updatedAt, including its addition to the constructor, schema, and creating getter/setter methods.

src/mappers/shlink-endpoint-mapper.test.ts (3)

20-21: Add deletedAt field to mockEntity

The addition of created_at and updated_at fields to the mockEntity object is good and aligns with the PR objectives. However, the PR summary mentions three timestamp fields, including deletedAt. Consider adding this field to the mockEntity for completeness:

const mockEntity: SHLinkEndpointEntity = {
  // ... existing fields ...
  created_at: dateValue,
  updated_at: dateValue,
  deleted_at: null  // or dateValue, depending on your use case
};

This ensures that all three timestamp fields mentioned in the PR objectives are represented in the test data.


29-30: Add deletedAt parameter to mockModel constructor

The addition of created_at and updated_at parameters to the SHLinkEndpointModel constructor is good and aligns with the PR objectives. However, to fully implement the changes described in the PR summary, consider adding the deletedAt parameter:

const mockModel = new SHLinkEndpointModel(
  'shlink-456',
  'config-789',
  '/api/path',
  'endpoint-123',
  dateValue,
  dateValue,
  null  // deletedAt parameter, or dateValue depending on your use case
);

This ensures that all three timestamp fields mentioned in the PR objectives are represented in the test data.


Line range hint 1-93: Overall review: Inconsistent implementation of timestamp fields

While the changes in this file partially implement the PR objectives by adding created_at and updated_at fields, there are several inconsistencies and omissions:

  1. The deletedAt field, mentioned in the PR objectives, is not implemented anywhere in the file.
  2. The new timestamp fields are added inconsistently across mockEntity, mockModel, and mockDto.
  3. The mapModelToEntity test doesn't include the new timestamp fields in its expected result.

Recommendations:

  1. Add the deletedAt field to all relevant parts of the file (mockEntity, mockModel, mockDto, and test expectations).
  2. Ensure consistent implementation of all three timestamp fields (createdAt, updatedAt, deletedAt) across all representations of SHLinkEndpoint in the test file.
  3. Update all relevant test expectations to include and validate the new timestamp fields.

These changes will ensure that the tests accurately reflect and validate the new schema changes described in the PR objectives.

src/mappers/server-config-mapper.ts (1)

Line range hint 1-79: Overall assessment: Changes align with PR objectives, but some improvements are recommended.

The additions of created_at and updated_at fields in the mapEntityToModel and mapModelToEntity functions align well with the PR objectives. However, consider the following recommendations:

  1. Verify that the database schema and ServerConfigModel have been updated to include these new timestamp fields.
  2. Consider including the timestamp fields in the DTO mapping (mapModelToDto) and model creation (mapDtoToModel) if they are relevant for API responses and application logic.
  3. There are inconsistencies between the AI-generated summary and the actual code regarding function signatures. Please review and update either the code or the PR description accordingly.

These changes will ensure a more comprehensive implementation of the timestamp fields across the entire mapping process.

src/mappers/user-mapper.test.ts (3)

12-13: LGTM! Consider using a more descriptive variable name.

The addition of the dateValue constant is good. It provides a consistent date for testing purposes.

Consider using a more descriptive name like testTimestamp or mockCreationDate to better reflect its purpose in the context of the new timestamp fields being added.


60-60: LGTM! Consider adding tests for timestamp fields.

The update to include server_config_id in the mapModelToEntity test is correct and consistent with the earlier changes.

Consider adding assertions for the new timestamp fields that were added to the UserModel constructor. This will ensure that these fields are correctly mapped between the model and entity.

Example:

expect(result).toEqual({
  id: userModel.getId(),
  user_id: userModel.getUserId(),
  patient_id: userModel.getPatientId(),
  server_config_id: userModel.getServerConfigId(),
  created_at: userModel.getCreatedAt(),
  updated_at: userModel.getUpdatedAt()
  // Add deletedAt if it's implemented
});

Line range hint 1-101: Overall good implementation, but some areas need attention.

The addition of server_config_id is consistently implemented across entity, model, and DTO. However, there are a few points that need attention:

  1. The PR objectives mention adding createdAt, updatedAt, and deletedAt fields, but only two date fields are visible in the changes. Please clarify if this is intentional or if a field is missing.

  2. The tests for mapModelToEntity, mapModelToDto, and mapDtoToModel should be updated to include assertions for the new timestamp fields.

  3. Consider adding tests to verify the correct initialization of the new fields in the UserModel constructor.

To ensure comprehensive coverage of the new fields:

  1. Update all relevant mapper tests to include assertions for server_config_id and timestamp fields.
  2. Add specific tests for the initialization and handling of the new timestamp fields in the UserModel.
  3. Ensure that the implementation aligns with the PR objectives regarding the three timestamp fields (createdAt, updatedAt, deletedAt).

These changes will improve the robustness of the tests and ensure that the new fields are correctly handled throughout the application.

src/usecases/shlinks/get-single-shlink.test.ts (2)

39-41: LGTM! Consider using a constant for the date value.

The addition of created_at, updated_at, and deleted_at fields to the mockSHLinkEntity is consistent with the PR objectives. The implementation looks correct.

For better maintainability, consider defining a constant for the date value:

const MOCK_DATE = new Date('2024-01-01T00:00:00Z');

// Then use it like this:
created_at: MOCK_DATE,
updated_at: MOCK_DATE,

This would make it easier to update the mock date across all fields if needed in the future.


54-56: LGTM! Consider improving consistency and type safety.

The addition of timestamp fields to the SHLinkModel constructor is consistent with the changes made to mockSHLinkEntity. The implementation looks correct.

Consider the following improvements:

  1. Use the mockSHLinkEntity properties directly for consistency:
mockSHLinkEntity.created_at,
mockSHLinkEntity.updated_at,
mockSHLinkEntity.deleted_at
  1. If you implement the constant suggestion from the previous comment, use it here as well:
MOCK_DATE,
MOCK_DATE,
null
  1. To improve type safety, consider using a type assertion for null:
null as Date | null

This ensures that the deleted_at field is correctly typed as Date | null.

src/usecases/shlinks/activate-shlink.test.ts (3)

41-43: LGTM! Consider using a constant for the fixed date.

The addition of created_at, updated_at, and deleted_at fields aligns well with the PR objectives. The initialization looks correct.

Consider defining a constant for the fixed date '2024-01-01T00:00:00Z' at the top of the test file. This would make it easier to update all occurrences if needed and improve readability. For example:

const FIXED_DATE = new Date('2024-01-01T00:00:00Z');

// Then use it like this:
created_at: FIXED_DATE,
updated_at: FIXED_DATE,

60-62: LGTM! Consider using the same constant for the fixed date.

The addition of timestamp fields to the SHLinkModel constructor is consistent with the changes in the entity. The values used are correct and maintain consistency with the mock entity data.

As suggested earlier, consider using a constant for the fixed date. This would make the test data more maintainable and reduce duplication. For example:

const FIXED_DATE = new Date('2024-01-01T00:00:00Z');

// Then use it like this:
FIXED_DATE,
FIXED_DATE,
null

Line range hint 1-105: Consider adding test cases for the new timestamp fields.

While the mock data has been updated to include the new timestamp fields (created_at, updated_at, and deleted_at), the current test cases don't explicitly verify the behavior related to these fields.

To ensure comprehensive test coverage, consider adding the following test cases:

  1. Verify that the activeSHLinksUseCase preserves the created_at timestamp when activating a SHLink.
  2. Check that the updated_at timestamp is modified when the SHLink is activated.
  3. Ensure that the deleted_at field remains null after activation.

Here's an example of how you might implement these test cases:

it('should preserve created_at and update updated_at when activating a SHLink', async () => {
  const result = await activeSHLinksUseCase(mockContext, { id: mockId });
  
  expect(result.created_at).toEqual(mockSHLinkEntity.created_at);
  expect(result.updated_at).not.toEqual(mockSHLinkEntity.updated_at);
  expect(result.updated_at.getTime()).toBeGreaterThan(mockSHLinkEntity.updated_at.getTime());
});

it('should keep deleted_at as null after activation', async () => {
  const result = await activeSHLinksUseCase(mockContext, { id: mockId });
  
  expect(result.deleted_at).toBeNull();
});

These additional tests will help ensure that the activeSHLinksUseCase correctly handles the new timestamp fields.

src/usecases/shlinks/add-shlink.test.ts (1)

64-66: LGTM: Mock entity updated correctly with new timestamp fields

The mockEntity object has been correctly updated with the new timestamp fields, maintaining consistency with the SHLinkModel. This change aligns well with the PR objectives.

For improved consistency and easier maintenance, consider using the same date constant for both the SHLinkModel constructor and the mockEntity object. For example:

const testDate = new Date('2024-01-01T00:00:00Z');

// Use testDate in both SHLinkModel constructor and mockEntity

This approach would make it easier to update the test date in the future if needed.

src/usecases/shlinks/deactivate-shlink.test.ts (3)

45-46: LGTM! Consider using a more realistic date for testing.

The addition of created_at and updated_at properties aligns well with the PR objectives. However, using a future date ('2024-01-01T00:00:00Z') for testing might not be ideal.

Consider using a past or present date for more realistic test scenarios. For example:

-      created_at: new Date('2024-01-01T00:00:00Z'),
-      updated_at: new Date('2024-01-01T00:00:00Z')
+      created_at: new Date('2023-01-01T00:00:00Z'),
+      updated_at: new Date('2023-01-01T00:00:00Z')

63-64: LGTM! Ensure consistency with the previous date change.

The addition of created_at and updated_at to the SHLinkModel constructor is consistent with the changes in the mock entity.

For consistency, update the date here as well if you change it in the mock entity:

-      new Date('2024-01-01T00:00:00Z'),
-      new Date('2024-01-01T00:00:00Z')
+      new Date('2023-01-01T00:00:00Z'),
+      new Date('2023-01-01T00:00:00Z')

Line range hint 1-114: Consider adding test cases for the new timestamp fields.

While the changes to include created_at and updated_at fields are good, the test suite doesn't explicitly verify any behavior related to these new fields.

Consider adding new test cases that:

  1. Verify that the created_at field remains unchanged after deactivation.
  2. Check that the updated_at field is modified when the SHLink is deactivated.

For example:

it('should not change the created_at field when deactivating', async () => {
  const result = await deactivateSHLinksUseCase(mockContext, {
    id: mockId,
    user: { id: 'user-123567', name: '', email: '' },
  });
  expect(result.created_at).toEqual(mockSHLinkEntity.created_at);
});

it('should update the updated_at field when deactivating', async () => {
  const result = await deactivateSHLinksUseCase(mockContext, {
    id: mockId,
    user: { id: 'user-123567', name: '', email: '' },
  });
  expect(result.updated_at).not.toEqual(mockSHLinkEntity.updated_at);
  expect(result.updated_at.getTime()).toBeGreaterThan(mockSHLinkEntity.updated_at.getTime());
});
src/mappers/shlink-mapper.ts (1)

Line range hint 1-124: Summary: Consistent implementation of createdAt and updatedAt, but deletedAt is missing

The changes in this file consistently implement the addition of createdAt and updatedAt fields across all mapping functions, which aligns with the PR objectives. The naming conventions are correctly maintained (snake_case for entities, camelCase for DTOs).

However, there's a recurring issue: the deletedAt field mentioned in the PR objectives is consistently missing across all functions.

Next steps:

  1. Add the deletedAt field to all mapping functions in this file.
  2. Ensure that the SHLinkModel, SHLinkEntity, SHLinkDto, and SHLinkMiniDto interfaces/classes are updated to include all three timestamp fields.
  3. Verify that these changes are consistently applied across the entire codebase, including other mapping functions and related interfaces/classes.

Consider creating a base interface or type for the timestamp fields (e.g., TimestampFields) and extending it in your entity, model, and DTO interfaces. This would ensure consistency and make it easier to manage these fields across your codebase.

Example:

interface TimestampFields {
  createdAt: Date;
  updatedAt: Date;
  deletedAt?: Date;
}

interface SHLinkDto extends TimestampFields {
  // other SHLink-specific fields
}

This approach would make it easier to maintain consistency and add or modify timestamp-related fields in the future.

src/usecases/shlinks/get-shlink.test.ts (2)

38-40: LGTM! Consider using a dynamic date for more realistic test data.

The addition of created_at, updated_at, and deleted_at fields aligns well with the PR objectives. The implementation is correct, with deleted_at appropriately set to null for an active record.

For more realistic test data, consider using new Date() for created_at and updated_at instead of a hardcoded date. This would make the tests more robust against future changes. For example:

created_at: new Date(),
updated_at: new Date(),
deleted_at: null

67-69: LGTM! Consider using dynamic dates for SHLinkModel instances as well.

The addition of timestamp fields to the SHLinkModel instances is correct and consistent with the changes made to the mock entities.

As suggested for the mock entities, consider using new Date() for created_at and updated_at in these SHLinkModel instances as well. This would make the tests more realistic and robust. For example:

new Date(), // created_at
new Date(), // updated_at
null // deleted_at

Also applies to: 80-82

src/usecases/shlinks/validate-shlink.test.ts (2)

19-21: LGTM! Consider using constants for clarity.

The addition of createdAt, updatedAt, and deletedAt timestamps is consistent with the PR objectives. Good job on implementing these changes.

For improved readability and maintainability, consider defining constants for these common timestamp values:

const MOCK_CREATED_AT = new Date('2024-01-01T00:00:00Z');
const MOCK_UPDATED_AT = new Date('2024-01-01T00:00:00Z');
const MOCK_DELETED_AT = null;

Then use these constants throughout the test file.


142-144: LGTM! Consistent implementation throughout the file.

The changes here maintain consistency with all previous instances. Great job on implementing these timestamp fields consistently across all test cases in the file.

Consider adding a test case that specifically checks the behavior of the validateSHLinkUseCase with respect to these new timestamp fields. For example, you could test whether a SHLink with a non-null deletedAt value is considered invalid.

src/usecases/shlinks/update-single-shlink.test.ts (1)

42-44: LGTM: New timestamp parameters added correctly to SHLinkModel constructor

The addition of timestamp parameters to the SHLinkModel constructor call is correct and consistent with the changes in mockDto.

Consider adding comments to clarify the purpose of these new parameters, especially the null value. For example:

new Date('2024-01-01T00:00:00Z'), // created_at
new Date('2024-01-01T00:00:00Z'), // updated_at
null // deleted_at

This would improve readability and make the purpose of each parameter more explicit.

prisma/schema.prisma (1)

Line range hint 1-129: Overall review: Timestamp fields added consistently, but one field is missing

The changes to add created_at and updated_at fields to all models in the Prisma schema are consistent and well-implemented. This will improve tracking of record lifecycles as intended.

However, there's a discrepancy between the PR objectives and the actual changes:

  1. The PR summary mentions adding three timestamp fields (createdAt, updatedAt, and deletedAt), but only two (created_at and updated_at) have been implemented.
  2. The deletedAt field is missing from all models.

Please address the following:

  1. Add the deletedAt field to all models, or explain why it was omitted.
  2. If deletedAt is not needed, update the PR description to reflect the actual changes.

Additionally, some models have existing time-related fields (access_time in shlink_access and refresh_time in server_config) that might overlap with the new timestamp fields. Consider reviewing these fields to ensure they serve distinct purposes and are still necessary.

src/mappers/server-config-mapper.test.ts (1)

25-26: LGTM: Good addition of timestamp fields. Minor formatting suggestion.

The addition of created_at and updated_at fields aligns with the PR objective.

Consider adding a space after the colon for consistency with other fields:

-    created_at:dateValue,
-    updated_at:dateValue
+    created_at: dateValue,
+    updated_at: dateValue
src/domain/dtos/shlink.ts (3)

93-108: LGTM: Addition of createdAt and updatedAt properties

The addition of createdAt and updatedAt properties to the SHLinkDto class is a good implementation of the PR objectives. These fields will improve tracking of the lifecycle of records in the database.

The properties are well-documented with appropriate descriptions and examples, using a consistent date format (ISO 8601) across the file.

There's a minor typo in the updatedAt type definition. Please apply this small fix:

-            type:datetime
+            type: datetime

This will ensure consistency with the createdAt type definition.


161-162: Addition of createdAt and updatedAt properties needs documentation

The addition of createdAt and updatedAt properties to the SHLinkMiniDto class is good and aligns with the PR objectives. However, these new properties are missing Swagger documentation, which is inconsistent with the documentation style in SHLinkDto.

Please add Swagger documentation for these new properties to maintain consistency. You can use the following as a template:

 *         createdAt:
 *           type: datetime
 *           description: A date representing when the share link was created.
 *           example: 2024-09-26T10:03:39.379Z
 *         updatedAt:
 *           type: datetime
 *           description: A date representing when the share link was last updated.
 *           example: 2024-09-26T10:03:39.379Z

Add deletedAt Field to DTOs for Complete Timestamp Tracking

The deletedAt field was not found in the SHLinkDto and SHLinkMiniDto classes. While it appears in the test files, its absence in the main DTOs suggests it was unintentionally omitted. To ensure complete timestamp tracking and consistency across the codebase, please add the deletedAt field to both DTO classes. Additionally, include appropriate Swagger documentation for this field.

  • Location to Update:
    • src/domain/dtos/shlink.ts
🔗 Analysis chain

Line range hint 1-220: Consider adding deletedAt field for complete timestamp tracking

The changes implement createdAt and updatedAt fields as per the PR objectives, which is great for tracking the creation and last update times of share links. However, I noticed that the deletedAt field mentioned in the PR objectives is not present in the changes.

If the omission of deletedAt was unintentional, consider adding it to both SHLinkDto and SHLinkMiniDto classes for complete timestamp tracking. This would align fully with the PR objectives of adding createdAt, updatedAt, and deletedAt fields to all tables.

If you decide to add the deletedAt field, please ensure it follows the same pattern as createdAt and updatedAt, including appropriate Swagger documentation.

To verify if deletedAt is implemented elsewhere or if it's intentionally omitted, we can run the following script:

This will help us understand if deletedAt is implemented elsewhere in the codebase or if it's consistently omitted.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for 'deletedAt' in all TypeScript files
rg --type typescript 'deletedAt'

# Search for soft delete implementation
rg --type typescript -i 'soft.*delete|delete.*at'

Length of output: 154


Script:

#!/bin/bash
# Search for 'deletedAt' in all TypeScript files
rg --type ts 'deletedAt'

# Search for soft delete implementation
rg --type ts -i 'soft.*delete|delete.*at'

Length of output: 848

src/domain/models/base-model.ts (2)

23-26: Reconsider passing createdAt and updatedAt as constructor parameters

Typically, createdAt is set when a new instance is created, and updatedAt is updated whenever the instance is modified. Passing these as optional parameters might lead to inconsistencies or accidental overwriting of these timestamps.

Consider initializing createdAt within the constructor and managing updatedAt through setters or within methods that modify the instance. Here's a suggested change:

  constructor(private _schema: ZodObject<ZodRawShape>) {
-    this.createdAt = createdAt;
-    this.updatedAt = updatedAt;
+    this.createdAt = new Date();
+    this.updatedAt = new Date();
  }

This approach sets the timestamps automatically, reducing the risk of errors from external assignment.


46-61: Evaluate the necessity of explicit getters and setters for public properties

Since createdAt and updatedAt are public properties, adding explicit getter and setter methods may be unnecessary unless additional logic is involved. This can make the code more concise and easier to maintain.

If no extra processing is needed in the getters and setters, you might remove them and access the properties directly:

-  getCreatedAt(): Date | undefined {
-    return this.createdAt;
-  }
-
-  setCreatedAt(createdAt: Date): void {
-    this.createdAt = createdAt;
-  }
-
-  getUpdatedAt(): Date | undefined {
-    return this.updatedAt;
-  }
-
-  setUpdatedAt(updatedAt: Date): void {
-    this.updatedAt = updatedAt;
-  }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between bbcd960 and 766b921.

📒 Files selected for processing (33)
  • prisma/schema.prisma (3 hunks)
  • prisma/schema.test.prisma (4 hunks)
  • src/domain/dtos/shlink-endpoint.ts (1 hunks)
  • src/domain/dtos/shlink.ts (3 hunks)
  • src/domain/models/access-ticket.ts (2 hunks)
  • src/domain/models/base-model.ts (3 hunks)
  • src/domain/models/server-config.ts (2 hunks)
  • src/domain/models/shlink-access.ts (1 hunks)
  • src/domain/models/shlink-endpoint.ts (1 hunks)
  • src/domain/models/shlink.ts (2 hunks)
  • src/domain/models/user.ts (1 hunks)
  • src/entities/base-entity.ts (1 hunks)
  • src/infrastructure/repositories/prisma/base-repository.ts (1 hunks)
  • src/mappers/access-ticket-mapper.test.ts (2 hunks)
  • src/mappers/access-ticket-mapper.ts (2 hunks)
  • src/mappers/server-config-mapper.test.ts (6 hunks)
  • src/mappers/server-config-mapper.ts (4 hunks)
  • src/mappers/shlink-access-mapper.test.ts (3 hunks)
  • src/mappers/shlink-access-mapper.ts (3 hunks)
  • src/mappers/shlink-endpoint-mapper.test.ts (2 hunks)
  • src/mappers/shlink-endpoint-mapper.ts (4 hunks)
  • src/mappers/shlink-mapper.test.ts (14 hunks)
  • src/mappers/shlink-mapper.ts (5 hunks)
  • src/mappers/user-mapper.test.ts (3 hunks)
  • src/mappers/user-mapper.ts (3 hunks)
  • src/usecases/shlink-qrcode/get-shlink-qrcode.test.ts (1 hunks)
  • src/usecases/shlinks/activate-shlink.test.ts (2 hunks)
  • src/usecases/shlinks/add-shlink.test.ts (2 hunks)
  • src/usecases/shlinks/deactivate-shlink.test.ts (2 hunks)
  • src/usecases/shlinks/get-shlink.test.ts (4 hunks)
  • src/usecases/shlinks/get-single-shlink.test.ts (2 hunks)
  • src/usecases/shlinks/update-single-shlink.test.ts (3 hunks)
  • src/usecases/shlinks/validate-shlink.test.ts (7 hunks)
🔇 Additional comments (71)
src/domain/models/access-ticket.ts (3)

17-18: LGTM! Verify BaseModel implementation.

The createdAt and updatedAt parameters are correctly passed to the superclass constructor.

To ensure proper implementation, verify that BaseModel correctly handles these timestamp fields:

#!/bin/bash
# Search for BaseModel implementation
rg --type typescript 'class BaseModel'

# Search for createdAt and updatedAt usage in BaseModel
rg --type typescript 'class BaseModel' -A 20 | rg 'createdAt|updatedAt'

Line range hint 1-38: Overall implementation looks good, with some suggestions for improvement.

The changes to AccessTicketModel align well with the PR objectives of adding timestamp fields. However, consider the following points:

  1. Add the deletedAt field to fully meet the PR objectives.
  2. Verify that BaseModel correctly implements the handling of these timestamp fields.
  3. Ensure consistency across other model classes in the project.

To check for consistency across the project, run:

#!/bin/bash
# Search for other model classes
rg --type typescript 'class \w+Model extends BaseModel'

# Check if they implement similar timestamp fields
rg --type typescript 'class \w+Model extends BaseModel' -A 10 | rg 'createdAt|updatedAt|deletedAt'

9-10: LGTM! Consider adding deletedAt parameter.

The addition of createdAt and updatedAt parameters aligns with the PR objectives. These timestamp fields will enhance the tracking of record lifecycles.

However, the PR objectives mention adding three timestamp fields, including deletedAt. Consider adding this parameter as well for consistency:

 constructor(
   private shlinkId: string,
   private id?: string,
   createdAt?: Date,
-  updatedAt?: Date
+  updatedAt?: Date,
+  deletedAt?: Date
 ) {

To verify if deletedAt is implemented in other models, run:

src/mappers/access-ticket-mapper.ts (1)

Line range hint 17-25: Verify intention: created_at and updated_at not mapped to entity

The change from shlink_id to getSHLinkId() is good, as it follows the principle of encapsulation by using a getter method instead of directly accessing the property.

However, I noticed that the created_at and updated_at fields are not being mapped back to the entity. This could potentially lead to data loss when converting from model to entity.

Could you please confirm if this is intentional? If not, consider updating the function to include these fields:

export const mapModelToEntity = (
  accessTicketModel: AccessTicketModel,
): AccessTicketEntity | undefined => {
  return accessTicketModel
    ? {
        id: accessTicketModel.getId(),
        shlink_id: accessTicketModel.getSHLinkId(),
        created_at: accessTicketModel.getCreatedAt(),
        updated_at: accessTicketModel.getUpdatedAt()
      }
    : undefined;
};

Also, to ensure consistency across the codebase, let's verify if other mapper files have been updated similarly:

src/domain/models/user.ts (1)

15-23: Verify handling of timestamp fields in BaseModel

The createdAt and updatedAt fields are correctly passed to the super() call. However, the validation schema doesn't include these new fields.

Please verify that the BaseModel class correctly handles these timestamp fields. If it doesn't, consider updating the validation schema to include them:

If BaseModel doesn't handle these fields, update the validation schema as follows:

super(
  z.object({
    userId: z.string().min(1),
    patientId: z.string().min(1),
    id: z.string().optional(),
    serverConfigId: z.string().optional(),
    createdAt: z.date().optional(),
    updatedAt: z.date().optional()
  }),
  createdAt,
  updatedAt
);

This ensures that all fields, including the new timestamp fields, are properly validated.

src/domain/models/shlink-endpoint.ts (2)

11-12: LGTM: Constructor signature updated correctly.

The addition of createdAt and updatedAt parameters to the constructor aligns with the PR objectives. These optional Date parameters are appropriately typed and follow the correct naming convention.


21-22: Verify BaseModel handling of timestamp fields.

The createdAt and updatedAt parameters are correctly passed to the superclass constructor. However, please ensure that the BaseModel class properly handles these timestamp fields.

To verify the BaseModel implementation, please run the following script:

✅ Verification successful

To continue verifying the BaseModel implementation, please run the following script:


To further verify how the BaseModel handles the createdAt and updatedAt fields, please run the following script:


BaseModel correctly handles timestamp fields.

The BaseModel class properly manages the createdAt and updatedAt fields. Passing these parameters to the superclass constructor is appropriate and correctly implemented.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the BaseModel implementation for timestamp handling

# Test: Search for BaseModel class definition and its handling of timestamp fields
rg --type typescript -A 10 'class BaseModel'

Length of output: 81


Script:

# 
#!/bin/bash
# Description: Check the BaseModel implementation for timestamp handling by searching within TypeScript files

# Search for the BaseModel class definition in .ts and .tsx files
rg -g "*.ts" -g "*.tsx" 'class BaseModel'

Length of output: 109


Script:

# 
#!/bin/bash
# Description: Check how BaseModel handles timestamp fields in base-model.ts

# Search for 'createdAt' and 'updatedAt' in base-model.ts
rg 'createdAt|updatedAt' src/domain/models/base-model.ts

Length of output: 538

src/mappers/user-mapper.ts (2)

46-50: ⚠️ Potential issue

Inconsistent mapping and missing timestamp fields

The formatting changes improve readability. However, there are a couple of issues to address:

  1. The newly added timestamp fields (created_at and updated_at) are not included in the mapping from UserDto to UserModel. This could lead to loss of data when converting from DTO to Model.

  2. The serverConfigId is now included in the mapping, which wasn't visible in the previous version. Ensure that this change is intentional and consistent with the UserDto definition.

Consider updating the UserModel constructor call to include the timestamp fields:

return userDto
  ? new UserModel(
      userDto.userId,
      userDto.patientId,
      userDto.id,
      userDto.serverConfigId,
      userDto.createdAt,
      userDto.updatedAt
    )
  : undefined;

Also, verify that the UserDto interface includes all these fields.

To verify the UserDto interface definition:

#!/bin/bash
# Search for UserDto interface definition
rg --type typescript 'interface UserDto' -A 10

14-15: Partial implementation of timestamp fields

The addition of created_at and updated_at fields aligns with the PR objectives. However, there are a couple of points to consider:

  1. The deletedAt field mentioned in the PR objectives is not included. Was this intentional?
  2. The order of parameters in the UserModel constructor has changed. Ensure that this change is reflected in the UserModel class definition and all other places where UserModel is instantiated.

To verify the UserModel constructor changes:

src/mappers/shlink-access-mapper.ts (3)

13-13: LGTM: Formatting improvement.

The removal of the trailing comma improves code consistency.


27-28: LGTM: Added timestamp fields to model mapping.

The addition of created_at and updated_at fields to the SHLinkAccessModel constructor aligns with the PR objectives.


41-41: LGTM: Formatting improvement.

The removal of the trailing comma improves code consistency.

src/mappers/access-ticket-mapper.test.ts (2)

46-46: LGTM! Improved consistency.

Removing the trailing comma after the shlink_id property improves consistency with other object literals in the file. This is a good minor style improvement.


Line range hint 11-22: Consider wrapping the entity object into a variable.

As suggested in a previous review, it would be beneficial to wrap the AccessTicketEntity object into a variable. This would improve readability and reduce duplication, as the same object is used later in the assertion.

Here's how you could implement this suggestion:

const entity: AccessTicketEntity = {
  id: '123',
  shlink_id: 'abc',
  created_at: dateValue,
  updated_at: dateValue
};

const model = mapEntityToModel(entity);

expect(model).toBeInstanceOf(AccessTicketModel);
expect(model?.getId()).toBe(entity.id);
expect(model?.getSHLinkId()).toBe(entity.shlink_id);
src/domain/models/shlink.ts (1)

15-16: Consider adding the deletedAt field.

The PR objectives mention adding three timestamp fields: createdAt, updatedAt, and deletedAt. However, only createdAt and updatedAt have been implemented. Was the omission of deletedAt intentional?

If deletedAt should be included, consider adding it:

private userId: string,
private name: string,
private passcodeFailuresRemaining?: number,
private active?: boolean,
private managementToken?: string,
private configPasscode?: string,
private configExp?: Date,
private id?: string,
createdAt?: Date,
updatedAt?: Date,
deletedAt?: Date

Don't forget to include it in the validation schema as well if you add it.

src/domain/models/server-config.ts (1)

19-20: LGTM: Constructor updated with new timestamp fields.

The addition of createdAt and updatedAt parameters to the constructor aligns with the PR objectives. These optional Date parameters will allow for better tracking of record lifecycles.

src/mappers/shlink-endpoint-mapper.test.ts (1)

12-13: LGTM: Addition of dateValue constant

The introduction of the dateValue constant is a good practice. It provides a consistent date value for testing the new timestamp fields, aligning with the PR objective of adding these fields to all tables.

src/mappers/user-mapper.test.ts (2)

35-35: LGTM! Consistent with entity and model changes.

The addition of serverConfigId to the userDto object is correct and follows the existing naming convention for DTOs.


19-19: LGTM! Verify consistency across the codebase.

The addition of server_config_id to the userEntity object is correct and follows the existing naming convention.

Please ensure that this new field is consistently added to all relevant user entity definitions across the codebase. Run the following script to verify:

src/usecases/shlinks/get-single-shlink.test.ts (1)

Line range hint 1-100: Overall, the changes look good. Verify test coverage for new fields.

The implementation of the new timestamp fields (created_at, updated_at, and deleted_at) in the test file is consistent with the PR objectives. The changes have been correctly applied to both the mock entity and the model.

To ensure comprehensive test coverage, please verify that the new timestamp fields are properly tested in all relevant test cases. Run the following command to check the test coverage for these new fields:

If the output doesn't show assertions for these fields, consider adding specific test cases to validate their behavior.

src/usecases/shlinks/add-shlink.test.ts (2)

50-52: LGTM: New timestamp fields added correctly

The addition of created_at, updated_at, and deleted_at fields to the SHLinkModel constructor aligns with the PR objectives. The use of a specific date for testing and setting deleted_at to null for a new entity are appropriate choices.


Line range hint 1-105: Consider adding explicit tests for new timestamp fields

While the mock objects have been updated with the new timestamp fields (created_at, updated_at, and deleted_at), the test cases themselves don't appear to explicitly verify the handling of these new fields.

To ensure comprehensive test coverage, consider adding or updating test cases to:

  1. Verify that the addShlinkUseCase correctly sets the created_at and updated_at fields when creating a new SHLink.
  2. Confirm that the deleted_at field is initially set to null for new SHLinks.
  3. Check that the mapper functions (mapModelToEntity and mapEntityToModel) correctly handle these new fields.

Here's a script to verify the current test coverage for these fields:

This script will help identify any existing coverage for the new fields and highlight areas where additional tests might be beneficial.

src/mappers/shlink-mapper.ts (5)

39-40: LGTM! Consider adding deleted_at field and verify getter methods.

The addition of created_at and updated_at fields to the entity object is consistent with the PR objectives. However, consider the following points:

  1. The deletedAt field mentioned in the PR objectives is not included. Consider adding it as deleted_at to maintain consistency with the snake_case naming convention used in the entity.

  2. The use of getCreatedAt() and getUpdatedAt() methods implies that these have been added to the SHLinkModel class.

Please ensure that these getter methods have been properly implemented in the SHLinkModel class. Run the following script to verify:

#!/bin/bash
# Description: Verify the implementation of new getter methods in SHLinkModel

# Test: Search for SHLinkModel class definition and its methods
echo "Checking SHLinkModel class definition:"
rg --type typescript "class SHLinkModel" -A 30

# Test: Specifically search for the new getter methods
echo "Checking for new getter methods:"
rg --type typescript "getCreatedAt\(\)|getUpdatedAt\(\)" -C 2

58-59: LGTM! Consider adding deletedAt field.

The addition of createdAt and updatedAt fields to the DTO object is consistent with the PR objectives and follows the correct camelCase naming convention for DTOs.

However, the deletedAt field mentioned in the PR objectives is not included. Consider adding it to maintain consistency with the PR goals.

To ensure consistency across the codebase, please run the following script:

#!/bin/bash
# Description: Verify consistent implementation of timestamp fields in DTOs

# Test: Search for SHLinkDto interface or type definition
echo "Checking SHLinkDto definition:"
rg --type typescript "interface SHLinkDto|type SHLinkDto" -A 15

# Test: Search for other DTO definitions to ensure consistency
echo "Checking other DTO definitions for timestamp fields:"
rg --type typescript "interface .*Dto|type .*Dto" -A 15 | rg "createdAt|updatedAt|deletedAt" -C 2

105-106: LGTM! Consider adding deletedAt field.

The addition of createdAt and updatedAt fields to the SHLinkModel constructor is consistent with the PR objectives and the changes made in other mapping functions.

However, the deletedAt field mentioned in the PR objectives is not included. Consider adding it to maintain consistency with the PR goals and other mapping functions.

To ensure consistency across the codebase, please run the following script:

#!/bin/bash
# Description: Verify consistent implementation of timestamp fields in DTO to Model mapping

# Test: Search for SHLinkModel constructor usage in mapping functions
echo "Checking SHLinkModel constructor usage in mapping functions:"
rg --type typescript "new SHLinkModel\(" -A 10

# Test: Search for other DTO to Model mapping functions to ensure consistency
echo "Checking other DTO to Model mapping functions for timestamp fields:"
rg --type typescript "mapDtoToModel|mapEntityToModel" -A 15 | rg "createdAt|updatedAt|deletedAt" -C 2

20-21: LGTM! Consider adding deletedAt field.

The addition of created_at and updated_at fields to the SHLinkModel constructor is consistent with the PR objectives. However, the deletedAt field mentioned in the PR objectives is not included.

Could you clarify if the deletedAt field should also be added to this mapping function? If so, please update the function accordingly.

To verify the consistency of these changes across the codebase, run the following script:


79-80: LGTM! Consider adding deletedAt field and verify MiniDTO interface.

The addition of createdAt and updatedAt fields to the MiniDTO object is consistent with the PR objectives and follows the correct camelCase naming convention for DTOs.

However, the deletedAt field mentioned in the PR objectives is not included. Consider adding it to maintain consistency with the PR goals.

To ensure consistency across the codebase, please run the following script:

src/usecases/shlinks/get-shlink.test.ts (2)

51-53: Consistent implementation of timestamp fields.

The addition of timestamp fields here is consistent with the previous mock entity.

Please refer to the previous comment regarding the use of new Date() for more realistic test data.


Line range hint 1-145: Overall, the changes look good and align with the PR objectives.

The implementation of created_at, updated_at, and deleted_at fields is consistent across mock entities and models. The changes enhance the test data to reflect the new schema accurately.

To ensure consistency across the codebase, let's verify if similar changes have been made in other test files:

This script will help identify any test files that might need similar updates and potential inconsistencies in the usage of timestamp fields.

✅ Verification successful

Verification Successful: All test files consistently implement the timestamp fields.

No inconsistencies found regarding created_at, updated_at, and deleted_at across the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent implementation of timestamp fields in test files.

# Test: Search for test files that might need similar updates
echo "Test files that might need timestamp field updates:"
rg --type typescript -g '*.test.ts' -l 'new SHLinkModel' | grep -v 'get-shlink.test.ts'

# Test: Check for inconsistent usage of timestamp fields
echo "\nPotential inconsistencies in timestamp field usage:"
rg --type typescript -g '*.test.ts' -n 'new SHLinkModel\([^)]+\)' | grep -vE '(created_at|updated_at|deleted_at)'

Length of output: 503


Script:

#!/bin/bash
# Description: Check for consistent implementation of timestamp fields in test files.

# Test: Search for test files that might need similar updates
echo "Test files that might need timestamp field updates:"
rg -g '*.test.ts' -l 'new SHLinkModel' | grep -v 'get-shlink.test.ts'

# Test: Check for inconsistent usage of timestamp fields
echo "\nPotential inconsistencies in timestamp field usage:"
rg -g '*.test.ts' -n 'new SHLinkModel\([^)]+\)' | grep -vE '(created_at|updated_at|deleted_at)'

Length of output: 923

src/usecases/shlinks/validate-shlink.test.ts (6)

40-42: Consistent implementation of timestamp fields.

The changes here are consistent with the previous instance, which is good for maintaining uniformity across test cases.

Please refer to the previous comment about using constants for these timestamp values to improve readability and maintainability.


62-64: LGTM! Consistent implementation.

The changes here maintain consistency with the previous instances, which is excellent for code uniformity.


84-86: LGTM! Maintaining consistency.

The changes continue to be consistent with previous instances, which is great for code readability and maintainability.


105-107: LGTM! Consistent implementation.

The changes here continue to maintain consistency with previous instances.


123-125: LGTM! Consistency maintained.

The changes continue to be consistent with previous instances, which is excellent for code uniformity.


Line range hint 1-156: Overall, excellent implementation of timestamp fields.

The changes in this file consistently add createdAt, updatedAt, and deletedAt fields to the SHLinkModel constructor in all test cases, which aligns well with the PR objectives. The implementation is uniform throughout the file, which is great for maintainability.

To further improve the code:

  1. Consider using constants for the timestamp values to enhance readability.
  2. Add a test case specifically for validating a SHLink with a non-null deletedAt value to ensure comprehensive coverage of the new fields.

Great job on this implementation!

prisma/schema.test.prisma (9)

13-14: LGTM: Timestamp fields added correctly

The created_at and updated_at fields have been properly added to the cas_item model. The use of @default(now()) for created_at and @updatedAt @default(now()) for updated_at ensures accurate tracking of record creation and modification times.


25-26: LGTM: Timestamp fields added consistently

The created_at and updated_at fields have been added to the shlink_file model, maintaining consistency with the cas_item model. The attributes are correctly applied to ensure proper tracking of creation and update times.


39-40: LGTM with a question: Timestamp fields added, but clarification needed

The created_at and updated_at fields have been correctly added to the shlink_access model. However, there's an existing access_time field that also defaults to the current timestamp.

Could you clarify the intended difference between access_time and created_at? If they serve different purposes, consider adding a comment to explain their distinct roles. If they are redundant, we might want to consider removing one of them.

Also applies to: 43-43


52-53: LGTM: Timestamp fields added correctly

The created_at and updated_at fields have been properly added to the shlink model, maintaining consistency with the other models. The attributes are correctly applied to ensure proper tracking of creation and update times.


73-74: LGTM: Timestamp fields added consistently

The created_at and updated_at fields have been correctly added to the user model, maintaining consistency with the other models. The attributes are properly applied to ensure accurate tracking of creation and update times.


87-88: LGTM with a question: Timestamp fields added, but clarification needed

The created_at and updated_at fields have been correctly added to the server_config model. However, there's an existing refresh_time field that also defaults to the current timestamp.

Could you clarify the intended difference between refresh_time and updated_at? If they serve different purposes, consider adding a comment to explain their distinct roles. If refresh_time is meant to track a specific type of update, it might be worth considering if it should use the @updatedAt attribute instead of @default(now()).

Also applies to: 94-94


104-105: LGTM: Timestamp fields added correctly

The created_at and updated_at fields have been properly added to the shlink_endpoint model, maintaining consistency with the other models. The attributes are correctly applied to ensure proper tracking of creation and update times.


119-120: LGTM: Timestamp fields added consistently

The created_at and updated_at fields have been correctly added to the access_ticket model, maintaining consistency with the other models. The attributes are properly applied to ensure accurate tracking of creation and update times.


Line range hint 1-124: Overall LGTM with minor clarifications needed

The changes in this PR successfully add created_at and updated_at timestamp fields to all models in the Prisma schema, which aligns with the stated objectives. The implementation is consistent across all models and follows best practices for tracking record creation and modification times.

However, there are two points that require clarification:

  1. In the shlink_access model, the relationship between the new created_at field and the existing access_time field needs to be explained.
  2. In the server_config model, the purpose of the refresh_time field in relation to the new updated_at field should be clarified.

Once these points are addressed, the changes will be fully ready for approval.

src/usecases/shlinks/update-single-shlink.test.ts (4)

28-30: LGTM: New timestamp fields added correctly

The addition of created_at, updated_at, and deleted_at fields to the mockDto object aligns with the PR objectives. The initialization of these fields with appropriate values (dates for creation and update, null for deletion) is correct and consistent.


56-58: LGTM: New timestamp fields added correctly to mockSHLinkEntity

The addition of created_at, updated_at, and deleted_at fields to the mockSHLinkEntity object is correct and consistent with the changes made to other mock objects. This ensures that the test data accurately reflects the new schema changes across all levels of the application.


Line range hint 1-158: Summary: New timestamp fields successfully added, consider enhancing test coverage

The changes to add created_at, updated_at, and deleted_at fields to the mock objects in this test file have been implemented correctly and consistently. These additions align well with the PR objectives of adding timestamp fields to all tables.

While the mock data structure has been updated appropriately, consider enhancing the test suite to explicitly verify the behavior of these new fields in various scenarios. This will ensure that the updateSingleSHLinkUseCase correctly handles these fields and maintains data integrity.

Overall, the changes look good, but additional test coverage would further strengthen the reliability of the code.


Line range hint 1-158: Consider adding test cases for new timestamp fields

While the mock objects have been updated to include the new created_at, updated_at, and deleted_at fields, the existing test cases don't explicitly verify the behavior related to these fields. To ensure comprehensive test coverage:

  1. Add a new test case that verifies the updated_at field is properly set when updating a SHLink.
  2. Modify the existing test cases to assert that created_at remains unchanged and deleted_at stays null after updates.
  3. Consider adding a test case for soft deletion if that's a feature of the system, verifying that deleted_at is set correctly.

These additions would help ensure that the new fields are properly handled by the use case and maintain data integrity.

To assist in identifying areas where additional tests might be needed, you can run the following command to check for usage of the new fields in the test file:

This will help identify if there are any existing assertions for the new fields, and highlight areas where additional test coverage might be beneficial.

prisma/schema.prisma (8)

11-17: LGTM: Timestamp fields added correctly to cas_item model

The created_at and updated_at fields have been added correctly to the cas_item model. The implementation follows Prisma best practices:

  • created_at uses @default(now()) to set the creation time.
  • updated_at uses @updatedAt to automatically update the timestamp on record modifications.

These additions will improve tracking of record lifecycles as intended.


23-25: LGTM: Timestamp fields added correctly to shlink_file model

The created_at and updated_at fields have been added correctly to the shlink_file model, consistent with the implementation in the cas_item model. This maintains consistency across the schema and fulfills the PR objectives.


51-52: LGTM: Timestamp fields added correctly to shlink model

The created_at and updated_at fields have been added correctly to the shlink model, consistent with the implementation in other models. This maintains consistency across the schema and fulfills the PR objectives.


73-74: LGTM: Timestamp fields added correctly to user model

The created_at and updated_at fields have been added correctly to the user model, consistent with the implementation in other models. This maintains consistency across the schema and fulfills the PR objectives.


108-109: LGTM: Timestamp fields added correctly to shlink_endpoint model

The created_at and updated_at fields have been added correctly to the shlink_endpoint model, consistent with the implementation in other models. This maintains consistency across the schema and fulfills the PR objectives.


123-124: LGTM: Timestamp fields added correctly to access_ticket model

The created_at and updated_at fields have been added correctly to the access_ticket model, consistent with the implementation in other models. This maintains consistency across the schema and fulfills the PR objectives.


89-90: LGTM with a suggestion: Clarify the purpose of refresh_time

The created_at and updated_at fields have been added correctly to the server_config model, consistent with other models. However, there's an existing refresh_time field that might overlap with updated_at.

Could you clarify the difference between refresh_time and updated_at? If they serve different purposes, please add a comment explaining their distinct roles. If refresh_time is no longer needed, consider removing it to avoid confusion.

To verify the usage of refresh_time, run the following script:

#!/bin/bash
# Description: Check for usage of refresh_time in the codebase

# Test: Search for refresh_time usage
rg --type typescript --type javascript 'refresh_time'

Also applies to: 98-98


37-43: LGTM with a suggestion: Clarify the purpose of access_time

The created_at and updated_at fields have been added correctly to the shlink_access model, consistent with other models. However, there's an existing access_time field that might overlap with created_at.

Could you clarify the difference between access_time and created_at? If they serve the same purpose, consider removing access_time to avoid redundancy. If they're different, please add a comment explaining their distinct purposes.

To verify the usage of access_time, run the following script:

✅ Verification successful

Verified: access_time is actively used across the codebase

The access_time field is referenced in multiple components, ensuring it serves a distinct purpose separate from the newly added created_at and updated_at fields. No redundancy issues detected.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usage of access_time in the codebase

# Test: Search for access_time usage
rg --type typescript --type javascript 'access_time'

Length of output: 88


Script:

#!/bin/bash
# Description: Check for usage of access_time in the codebase

# Test: Search for access_time usage
rg --type typescript --type javascript 'access_time'

Length of output: 87


Script:

#!/bin/bash
# Description: Check for usage of access_time in TypeScript and JavaScript files

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

Length of output: 877

src/mappers/server-config-mapper.test.ts (4)

12-12: LGTM: Good addition of a date constant for testing.

The addition of dateValue constant with a specific UTC date is a good practice for consistent date handling in tests.


38-38: LGTM: Consistent removal of trailing comma.

The removal of the trailing comma after 'entity-refresh-token' is consistent with other similar changes in the file.


50-50: LGTM: Consistent removal of trailing commas in object literals.

The removal of trailing commas in object literals at lines 50, 94, and 116 is consistent with earlier changes and maintains a uniform coding style throughout the file.

Also applies to: 94-94, 116-116


Line range hint 1-146: Consider updating tests to cover new timestamp fields.

While the changes align with the PR objectives and improve code consistency, the tests haven't been updated to check the new created_at and updated_at fields. Consider adding assertions for these fields in the relevant test cases, particularly in the mapEntityToModel and mapModelToEntity tests.

To verify the current test coverage for the new fields, you can run the following command:

If this command doesn't return any results, it confirms that the new fields are not being tested yet.

src/domain/dtos/shlink.ts (1)

84-84: LGTM: Improved example for configExp

The update to the configExp example with a specific date (2024-09-26T10:03:39.379Z) is a good improvement. It provides a clear, concrete example of the expected date format (ISO 8601), which enhances the API documentation and helps developers understand the expected input.

src/mappers/shlink-mapper.test.ts (9)

14-15: LGTM: Good practice for test date consistency

The introduction of the dateValue constant is a good practice. It ensures consistency across the test file and makes it easier to update the date value if needed in the future.


25-27: LGTM: Timestamp fields added as per PR objective

The addition of config_exp, created_at, and updated_at fields to shLinkEntity aligns with the PR objective. Using the dateValue constant ensures consistency across the test file.


37-37: LGTM: SHLinkModel constructor updated correctly

The SHLinkModel constructor has been correctly updated to include the new timestamp fields. The use of dateValue ensures consistency, and the placement of the new parameters at the end of the constructor call is correct.

Also applies to: 39-40


51-53: LGTM: DTO updated with correct naming convention

The shLinkDto object has been correctly updated with the new timestamp fields. The use of camelCase for the DTO fields (configExp, createdAt, updatedAt) follows the correct naming convention, and the use of dateValue ensures consistency across the test file.


89-90: LGTM: mapModelToEntity test updated correctly

The mapModelToEntity function test has been correctly updated to include the new timestamp fields. The use of getter methods (getCreatedAt() and getUpdatedAt()) is consistent with the other fields in the test.


112-114: LGTM: mapModelToDto test updated correctly

The mapModelToDto function test has been correctly updated to include the new timestamp fields. The use of getter methods and the camelCase naming convention for the DTO fields are correct and consistent with the rest of the test.


159-160: LGTM: Model constructors updated consistently

The constructors for SHLinkModel and SHLinkEndpointModel have been consistently updated across all test cases to include the new timestamp fields. The use of dateValue ensures consistency, and the placement of the new parameters at the end of the constructor calls is correct.

Also applies to: 169-170, 177-178, 266-267, 276-277


195-196: LGTM: mapModelToMiniDto tests updated correctly

The expected results in the mapModelToMiniDto tests have been correctly updated to include the new timestamp fields. The use of dateValue ensures consistency, and the camelCase naming convention for the DTO fields is correct.

Also applies to: 240-241, 293-294


Line range hint 1-304: Overall: Excellent implementation of timestamp fields

The changes in this file comprehensively address the PR objective of adding timestamp fields (createdAt, updatedAt) to all relevant objects and test cases. The implementation is consistent, using the dateValue constant throughout, which ensures easy maintenance. All necessary areas of the test file have been updated, including entity objects, models, DTOs, and various mapping function tests. The changes follow correct naming conventions and are well-integrated into the existing test structure.

Great job on maintaining consistency and thoroughness throughout the file!

src/mappers/shlink-access-mapper.test.ts (1)

139-139: Verify if createdAt and updatedAt should be included in the DTO.

The SHLinkAccessDto currently does not include createdAt and updatedAt. If these fields are intended to be exposed via the DTO, update the mapModelToDto function and the test accordingly.

Do you need assistance in updating the DTO and related mappings to include these fields?

src/entities/base-entity.ts Show resolved Hide resolved
src/domain/models/user.ts Show resolved Hide resolved
src/domain/models/shlink-endpoint.ts Show resolved Hide resolved
src/domain/models/shlink-endpoint.ts Show resolved Hide resolved
src/domain/models/shlink-access.ts Show resolved Hide resolved
src/mappers/user-mapper.test.ts Show resolved Hide resolved
src/domain/models/base-model.ts Show resolved Hide resolved
src/mappers/shlink-access-mapper.test.ts Outdated Show resolved Hide resolved
src/mappers/shlink-access-mapper.test.ts Outdated Show resolved Hide resolved
src/mappers/shlink-access-mapper.test.ts Outdated Show resolved Hide resolved
Copy link

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

🧹 Outside diff range and nitpick comments (13)
src/usecases/shlinks/deactivate-shlink.ts (1)

11-24: Overall improvement in code structure with a minor suggestion.

The refactoring to a model-based approach significantly improves the code structure and maintainability. It aligns well with the PR objectives of enhancing data management.

However, there's a minor inconsistency in error handling:

Consider adding an explicit check for the existence of the model before proceeding with the authorization check. This would provide clearer error messages and maintain consistency with the entity-based approach. Here's a suggested improvement:

 const model = mapEntityToModel(await context.repo.findById(data.id));

 let newShlink: SHLinkEntity;

 if (model) {
+  if (!model) {
+    throw new Error('SHLink not found');
+  }
   if (data.user.id !== model.getUserId())
     throw new AuthenticationError(
       'User not authorized to deactivate shlink.',
     );

   model.setActive(false);
   newShlink = await context.repo.update(mapModelToEntity(model));
 }

 return mapEntityToModel(newShlink);

This change would ensure that a clear error is thrown if the SHLink is not found, improving error handling and debugging.

src/usecases/shlinks/update-single-shlink.ts (1)

31-32: Good changes: Consistent use of model and proper layer separation.

The modifications to use the model in the validator call and map it back to an entity for the repository update are good practices. They maintain consistency and proper separation between domain and persistence layers.

However, a minor improvement could be made:

Consider extracting the model-to-entity mapping to a separate line for better readability:

- updateShlink = await context.repo.update(mapModelToEntity(model));
+ const entityToUpdate = mapModelToEntity(model);
+ updateShlink = await context.repo.update(entityToUpdate);

This change would make the code slightly more readable and easier to debug if needed.

Also applies to: 35-35

src/usecases/shlinks/update-single-shlink.test.ts (3)

27-39: LGTM: Detailed mock entity and model setup

The mock entity and model setups are now more comprehensive, including necessary methods for testing. The mapper function mocks are correctly configured to return the mock model and entity.

Consider adding a setActive method to the mock model for consistency, as it might be useful in future tests:

 mockModel = {
   id: '1',
   active: false,
   setConfigPasscode: jest.fn(),
   setConfigExp: jest.fn(),
   getConfigPasscode: jest.fn().mockReturnValue('1234'),
+  setActive: jest.fn(),
 } as unknown as SHLinkModel;

42-63: LGTM: Comprehensive test for updating passcode and expiry date

This test case thoroughly checks the behavior of updateSingleSHLinkUseCase when updating both passcode and expiry date. It verifies all expected method calls and the final result.

Consider adding an assertion to check if mapModelToEntity was called before repo.update:

 expect(repo.update).toHaveBeenCalledWith(mockEntity);
+expect(mapModelToEntity).toHaveBeenCalledWith(mockModel);
 expect(result).toBe(mockModel);

This ensures that the model is correctly mapped back to an entity before updating the repository.


90-104: LGTM with suggestion: Error handling test

This test case effectively verifies that the updateSingleSHLinkUseCase throws an error when validation fails. The use of rejects.toThrow() is appropriate for testing asynchronous error handling.

Consider adding assertions to verify the behavior before the error is thrown:

 // Arrange
 const data = { id: '1', passcode: 'invalidPasscode' };
 repo.findOne.mockResolvedValue(mockEntity);
 mockValidator.mockImplementation(() => {
   throw new Error('Validation failed');
 });

+// Act
+const updatePromise = updateSingleSHLinkUseCase(
+  { repo, validator: mockValidator },
+  data
+);
+
 // Act & Assert
-await expect(
-  updateSingleSHLinkUseCase(
-    { repo, validator: mockValidator },
-    data
-  )
-).rejects.toThrow('Validation failed');
+await expect(updatePromise).rejects.toThrow('Validation failed');
+
+// Additional assertions
+expect(repo.findOne).toHaveBeenCalledWith({ id: data.id });
+expect(mockModel.setConfigPasscode).toHaveBeenCalledWith(data.passcode);
+expect(mockValidator).toHaveBeenCalled();
+expect(repo.update).not.toHaveBeenCalled();

These additional assertions will ensure that the expected methods are called before the error is thrown, and that the repository update is not called after the validation fails.

src/usecases/shlinks/deactivate-shlink.test.ts (3)

19-20: Consider using a more flexible date value.

While using a constant date value helps maintain consistency across test cases, setting it to a future date (2024) might not be ideal for all test scenarios. Consider using a dynamic date that's closer to the current date, or use a library like jest-date-mock to have more control over the date in your tests.

You could replace the current implementation with:

const dateValue = new Date();

Or, if you want to use a fixed date that's not in the future:

const dateValue = new Date('2023-01-01T00:00:00Z');

Line range hint 22-33: LGTM: Mock setup updated correctly with a minor suggestion.

The changes in the mock setup are consistent with the new fields added to the entities. The use of jest.Mocked<ISHLinkRepository> provides better type checking for mocked methods, which is a good practice.

Consider destructuring the dateValue when setting multiple fields to the same value in mockSHLinkEntity:

mockSHLinkEntity = {
  // ... other fields
  config_exp: dateValue,
  created_at: dateValue,
  updated_at: dateValue,
};

This can make the code more concise and easier to maintain.

Also applies to: 35-35, 48-50, 55-55, 67-68, 75-76


110-121: LGTM: Excellent addition of authentication error test.

This new test case significantly improves the overall test coverage by checking the authentication logic. It correctly verifies that findById is called but update is not called when the user is unauthorized.

Consider adding a more specific error message check to ensure the correct error is thrown:

await expect(
  deactivateSHLinksUseCase(mockContext, {
    id: mockId,
    user: { id: wrongUserId, name: '', email: '' },
  }),
).rejects.toThrow('User is not authorized to deactivate this SHLink');

This will make the test more robust against potential changes in error messages.

prisma/migrations/20240927083507_/migration.sql (5)

1-11: LGTM! Consider adding a table comment.

The cas_item table creation looks good and aligns with the PR objectives. The timestamp fields are correctly included, and appropriate data types are used for each column.

Consider adding a comment to explain the purpose of this table. For example:

COMMENT ON TABLE "cas_item" IS 'Stores content-addressable storage items with their hashes and reference counts';

25-35: LGTM! Consider revising access_time default.

The shlink_access table creation looks good and aligns with the PR objectives. The timestamp fields are correctly included.

Consider removing the default value for access_time:

-    "access_time" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "access_time" TIMESTAMP(3) NOT NULL,

This allows for explicitly setting the access time, which might differ from the record creation time. If you want to keep the default, consider explaining why it's needed in addition to created_at.

Also, consider adding a table comment to explain the purpose of this table and its relationship to other tables.


85-95: LGTM! Consider adding a unique constraint.

The shlink_endpoint table creation looks good and aligns with the PR objectives. The timestamp fields are correctly included.

Consider adding a unique constraint to ensure that each combination of shlink_id, server_config_id, and url_path is unique:

ALTER TABLE "shlink_endpoint" ADD CONSTRAINT "unique_shlink_endpoint" UNIQUE ("shlink_id", "server_config_id", "url_path");

This constraint would prevent duplicate entries and maintain data integrity.

Also, add a table comment to explain the purpose of this table and its relationship to other tables.


164-186: LGTM! Consider consistent ON DELETE behavior.

The foreign key constraints look good and maintain referential integrity between tables.

For consistency, consider standardizing the ON DELETE behavior across all foreign key constraints. Currently, you're using a mix of SET NULL and RESTRICT. Unless there's a specific reason for this variation, it might be clearer to use RESTRICT consistently:

-ALTER TABLE "shlink_file" ADD CONSTRAINT "shlink_file_content_hash_fkey" FOREIGN KEY ("content_hash") REFERENCES "cas_item"("hash") ON DELETE SET NULL ON UPDATE CASCADE;
+ALTER TABLE "shlink_file" ADD CONSTRAINT "shlink_file_content_hash_fkey" FOREIGN KEY ("content_hash") REFERENCES "cas_item"("hash") ON DELETE RESTRICT ON UPDATE CASCADE;

-ALTER TABLE "user" ADD CONSTRAINT "user_server_config_id_fkey" FOREIGN KEY ("server_config_id") REFERENCES "server_config"("id") ON DELETE SET NULL ON UPDATE CASCADE;
+ALTER TABLE "user" ADD CONSTRAINT "user_server_config_id_fkey" FOREIGN KEY ("server_config_id") REFERENCES "server_config"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

This change would ensure that no records can be deleted if they are referenced by other tables, providing a consistent safeguard against data loss. However, if the current mixed approach is intentional based on your application's requirements, please clarify the reasoning in comments for future maintainers.


1-186: Overall, well-structured migration with some areas for improvement.

This migration successfully implements the PR objectives by adding timestamp fields to all tables and creating a comprehensive database schema. Here's a summary of key points to address:

  1. Security:

    • Remove plain text storage of passwords and secrets (e.g., config_passcode, config_client_secret).
    • Consider encrypting sensitive fields like config_refresh_token and access_token_response.
  2. Optimization:

    • Review and remove redundant indexes, especially on primary key columns.
    • Consider adding composite indexes based on query patterns.
  3. Consistency:

    • Standardize ON DELETE behavior for foreign key constraints.
    • Ensure consistent naming conventions across all tables and constraints.
  4. Documentation:

    • Add table comments to explain the purpose of each table and its relationships.
  5. Validation:

    • Clarify the purpose of the access_ticket table and its relationship to other tables.
    • Verify the necessity of both id and user_id in the user table.

Address these points to enhance the security, performance, and maintainability of your database schema.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between a72417f and bca4f28.

📒 Files selected for processing (11)
  • prisma/migrations/20240927083507_/migration.sql (1 hunks)
  • prisma/migrations/20240927084525_/migration.sql (1 hunks)
  • src/domain/models/base-model.ts (3 hunks)
  • src/mappers/shlink-mapper.test.ts (13 hunks)
  • src/mappers/shlink-mapper.ts (5 hunks)
  • src/usecases/shlinks/activate-shlink.test.ts (4 hunks)
  • src/usecases/shlinks/activate-shlink.ts (1 hunks)
  • src/usecases/shlinks/deactivate-shlink.test.ts (6 hunks)
  • src/usecases/shlinks/deactivate-shlink.ts (1 hunks)
  • src/usecases/shlinks/update-single-shlink.test.ts (1 hunks)
  • src/usecases/shlinks/update-single-shlink.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/domain/models/base-model.ts
  • src/mappers/shlink-mapper.test.ts
  • src/mappers/shlink-mapper.ts
  • src/usecases/shlinks/activate-shlink.test.ts
🔇 Additional comments (17)
prisma/migrations/20240927084525_/migration.sql (1)

1-8: Consider alternatives to dropping the deleted_at column.

Dropping the deleted_at column will result in permanent data loss, as warned in the comment. This column is typically used for soft deletes, which can be beneficial for data recovery and auditing purposes.

Before proceeding with this change, please consider the following:

  1. Is the data in this column no longer needed? If it's valuable, consider exporting it before dropping the column.
  2. Are there any dependencies in the application code that rely on this column? Removing it might cause runtime errors if not handled properly.
  3. Instead of dropping the column, could it be repurposed or renamed to fit the new schema design?

If you decide to proceed with dropping the column, ensure that all related application code is updated accordingly to prevent any potential issues.

To help assess the impact, let's check for usage of the deleted_at column in the codebase:

✅ Verification successful

Dropping the deleted_at column is verified safe.

No references to deleted_at were found in the application codebase, indicating no dependencies. You can proceed with removing the column as planned.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for usage of the deleted_at column in the codebase

# Search for 'deleted_at' in TypeScript/JavaScript files
echo "TypeScript/JavaScript files referencing 'deleted_at':"
rg --type-add 'ts:*.{ts,js}' --type ts 'deleted_at' -l

# Search for 'deleted_at' in SQL files
echo "SQL files referencing 'deleted_at':"
rg --type sql 'deleted_at' -l

# Search for 'deletedAt' in TypeScript/JavaScript files (camelCase variant)
echo "TypeScript/JavaScript files referencing 'deletedAt':"
rg --type-add 'ts:*.{ts,js}' --type ts 'deletedAt' -l

Length of output: 565

src/usecases/shlinks/deactivate-shlink.ts (2)

5-5: LGTM: Good separation of concerns with mapper functions.

The addition of mapEntityToModel and mapModelToEntity imports from a dedicated mapper file is a positive change. It promotes better separation of concerns and improves code maintainability.


11-12: LGTM: Improved separation of concerns with model-based approach.

The changes effectively implement a model-based approach:

  1. Using mapEntityToModel to work with a model instead of an entity.
  2. Utilizing model methods like getUserId() and setActive() for better encapsulation.
  3. Applying mapModelToEntity before updating the repository.

These changes enhance the separation between entity and model layers, improving code clarity and maintainability.

Also applies to: 15-22

src/usecases/shlinks/update-single-shlink.ts (4)

4-4: LGTM: Import statement updated correctly.

The addition of mapModelToEntity import is consistent with the changes described in the summary and supports the bidirectional mapping between entity and model.


21-21: Excellent: Improved entity-to-model mapping.

The change to map the repository result to a model (mapEntityToModel) is a good practice. It enhances type safety, allows for the use of model-specific methods, and maintains a clear separation between the persistence layer (entities) and the domain layer (models).


24-24: Great improvement: Using model methods for updates.

The changes to use model.setConfigPasscode() and model.setConfigExp() instead of directly modifying properties are excellent. This approach:

  1. Encapsulates the update logic within the model.
  2. Allows for additional validation or business logic in the setter methods.
  3. Improves maintainability and adheres to the single responsibility principle.

Also applies to: 27-27


Line range hint 1-38: Overall excellent improvements to code structure and design.

The changes in this file significantly enhance the separation of concerns between the domain and persistence layers, consistently using the SHLinkModel throughout the use case. This approach improves type safety, encapsulation, and maintainability.

To ensure consistency across the codebase:

  1. Verify that similar changes have been applied to other use cases dealing with SHLinks.
  2. Consider creating (if not already present) or updating architecture documentation to reflect this approach of using mappers and working primarily with domain models in use cases.

To check for consistency, we can search for other files that might need similar updates:

This will help identify other areas of the codebase that might benefit from similar refactoring.

✅ Verification successful

To effectively verify the consistency of changes across the codebase, let's adjust the shell scripts to target .ts files directly.


Verification Successful: The refactoring changes in update-single-shlink.ts are consistently applied across the codebase. No direct accesses to SHLinkEntity properties remain, and mapper functions are appropriately used in all relevant use cases.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other files that might need similar updates
echo "Files potentially needing similar updates:"
rg --type typescript 'export const \w+SHLinkUseCase' --files-with-matches

echo "\nFiles still directly accessing SHLinkEntity properties:"
rg --type typescript 'SHLinkEntity.*\.(configPasscode|configExp)' -l

echo "\nFiles not using mapEntityToModel or mapModelToEntity:"
rg --type typescript 'ISHLinkRepository' -l | xargs rg --type typescript -L '(mapEntityToModel|mapModelToEntity)'

Length of output: 741


Script:

#!/bin/bash
# Search for other files that might need similar updates
echo "Files potentially needing similar updates:"
rg 'export const \w+SHLinkUseCase' -g "*.ts" --files-with-matches

echo "\nFiles still directly accessing SHLinkEntity properties:"
rg 'SHLinkEntity.*\.(configPasscode|configExp)' -g "*.ts" -l

echo "\nFiles not using mapEntityToModel or mapModelToEntity:"
rg 'ISHLinkRepository' -g "*.ts" -l | xargs rg -L '(mapEntityToModel|mapModelToEntity)'

Length of output: 6389

src/usecases/shlinks/update-single-shlink.test.ts (3)

4-4: LGTM: Improved import and mock setup

The addition of mapModelToEntity import and mocking the entire mapper module enhances the test setup, allowing for more comprehensive testing of bi-directional mapping between entities and models.

Also applies to: 8-9


12-22: LGTM: Comprehensive mock setup

The mock repository and validator setups are well-structured. The repository mock includes both findOne and update methods, which are crucial for testing the use case. The validator mock is appropriately set up as a simple jest mock function.

Also applies to: 24-25


66-87: LGTM: Proper handling of undefined inputs

This test case effectively verifies that the updateSingleSHLinkUseCase doesn't modify passcode or expiry date when they're not provided in the input. It correctly checks that the setter methods are not called and that the validator is still invoked with the existing data.

src/usecases/shlinks/deactivate-shlink.test.ts (4)

5-9: LGTM: Imports and mocks updated appropriately.

The new imports and mocks are consistent with the changes in the test suite. The AuthenticationError import suggests a new test case for authentication, which is a good addition for comprehensive testing.

Also applies to: 16-16


78-80: LGTM: Good practice to clear mocks after each test.

Adding an afterEach block to clear mocks after each test is an excellent practice. This ensures that each test starts with a clean slate, improving test isolation and preventing potential state pollution between tests.


125-125: LGTM: Improved error handling test.

The changes in the error handling test are well-implemented. Using mockRejectedValue is the correct way to simulate a rejected promise in Jest. The added expectation ensures that the update method is called with the correct argument before throwing an error, which improves the test's thoroughness.

Also applies to: 134-134


Line range hint 1-136: Overall, excellent improvements to the test suite.

The changes in this file align well with the PR objectives of adding timestamp fields (created_at, updated_at) to all tables. The test suite has been significantly improved with:

  1. Better type checking for mocked repositories.
  2. Consistent use of new timestamp fields in mock data.
  3. Additional test case for authentication errors.
  4. Improved error handling tests.
  5. Better test isolation with the addition of afterEach cleanup.

These changes enhance the overall quality and coverage of the deactivateSHLinksUseCase tests. The only minor point for consideration is the use of a fixed future date for dateValue, which could be made more flexible for robust testing across different scenarios.

Great job on improving the test suite!

prisma/migrations/20240927083507_/migration.sql (3)

13-23: LGTM! Clarify content_type default and nullable content_hash.

The shlink_file table creation looks good and aligns with the PR objectives. The timestamp fields are correctly included.

Please clarify the following:

  1. Is 'application/json' the most appropriate default for content_type? Will most files be JSON, or should this be left NULL by default?
  2. Why is content_hash nullable? If it's meant to reference cas_item.hash, should it be required?

Consider adding a table comment to explain the purpose of this table and its relationship to other tables.


55-65: LGTM! Clarify id/user_id redundancy and patient_id constraint.

The user table creation looks good and aligns with the PR objectives. The timestamp fields are correctly included.

Please clarify the following:

  1. Is there a need for both id and user_id? If user_id is meant to be an external identifier, consider renaming it to clarify its purpose (e.g., external_user_id).
  2. Is patient_id always required? If not all users are patients, consider making this field nullable:
-    "patient_id" TEXT NOT NULL,
+    "patient_id" TEXT,

Also, consider adding a table comment to explain the purpose of this table and its relationship to other tables.


97-105: LGTM! Clarify the purpose of access_ticket table.

The access_ticket table creation looks good and aligns with the PR objectives. The timestamp fields are correctly included.

Please clarify the purpose of this table. It seems to be related to shlink, but its exact function is not clear from the structure. Consider:

  1. Adding more fields if necessary to fully represent an "access ticket".
  2. Adding a table comment to explain its purpose and relationship to other tables.
  3. If it's meant to be a one-to-one relationship with shlink, consider adding a unique constraint on shlink_id:
ALTER TABLE "access_ticket" ADD CONSTRAINT "unique_access_ticket_shlink" UNIQUE ("shlink_id");

This additional information will help in understanding the table's role in the overall schema.

Comment on lines 1 to +104
passcode: '1234',
});

// Verify mapper and result
expect(mapEntityToModel).toHaveBeenCalledWith(updatedSHLinkEntity);
expect(result).toEqual(mockSHLinkModel);
expect(repo.update).toHaveBeenCalledWith(mockEntity);
expect(result).toBe(mockModel);
});

it('should not update config_passcode or config_exp if they are not set in the data', async () => {
const mockSHLinkModelWithoutFields = new SHLinkModel(
mockSHLinkModel.getUserId(),
mockSHLinkModel.getName(),
mockSHLinkModel.getPasscodeFailuresRemaining(),
mockSHLinkModel.getActive(),
mockSHLinkModel.getManagementToken(),
undefined, // No configPasscode
undefined, // No configExp
'1',
);

const entityWithoutConfig: SHLinkEntity = {
...mockSHLinkEntity,
config_passcode: mockSHLinkEntity.config_passcode, // Should remain unchanged
config_exp: mockSHLinkEntity.config_exp, // Should remain unchanged
};
it('should not set passcode or expiry date if they are not provided', async () => {
// Arrange
const data = { id: '1' }; // No passcode or expiry date
repo.findOne.mockResolvedValue(mockEntity);
repo.update.mockResolvedValue(mockEntity);

// Mock repository behavior
mockRepo.findOne.mockResolvedValue(mockSHLinkEntity);
mockRepo.update.mockResolvedValue(entityWithoutConfig);
(mapEntityToModel as jest.Mock).mockReturnValue(
mockSHLinkModelWithoutFields,
);

// Call the use case
// Act
const result = await updateSingleSHLinkUseCase(
{ repo: mockRepo, validator: jest.fn().mockResolvedValue(true) }, // Mock validator
{ id: '1' }, // No passcode or expiryDate provided
{ repo, validator: mockValidator },
data
);

// Verify repository interactions
expect(mockRepo.findOne).toHaveBeenCalledWith({ id: '1' });
expect(mockRepo.update).toHaveBeenCalledWith(entityWithoutConfig);

// Verify result
expect(result).toEqual(mockSHLinkModelWithoutFields);
// Assert
expect(repo.findOne).toHaveBeenCalledWith({ id: data.id });
expect(mockModel.setConfigPasscode).not.toHaveBeenCalled();
expect(mockModel.setConfigExp).not.toHaveBeenCalled();
expect(mockValidator).toHaveBeenCalledWith({
shlink: mockModel,
passcode: '1234',
});
expect(repo.update).toHaveBeenCalledWith(mockEntity);
expect(result).toBe(mockModel);
});

it('should call validator before updating', async () => {
const mockValidator = jest.fn().mockResolvedValue(true);

// Mock repository behavior
mockRepo.findOne.mockResolvedValue(mockSHLinkEntity);
mockRepo.update.mockResolvedValue(mockSHLinkEntity);
(mapEntityToModel as jest.Mock).mockReturnValue(mockSHLinkModel);

// Call the use case
await updateSingleSHLinkUseCase(
{ repo: mockRepo, validator: mockValidator },
{ id: '1', passcode: 'new-passcode' },
);

// Verify validator call
expect(mockValidator).toHaveBeenCalledWith({
shlink: mockSHLinkModel,
passcode: 'new-passcode',
it('should throw an error if the validator fails', async () => {
// Arrange
const data = { id: '1', passcode: 'invalidPasscode' };
repo.findOne.mockResolvedValue(mockEntity);
mockValidator.mockImplementation(() => {
throw new Error('Validation failed');
});

// Act & Assert
await expect(
updateSingleSHLinkUseCase(
{ repo, validator: mockValidator },
data
)
).rejects.toThrow('Validation failed');
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Suggestion: Consider adding more test cases for improved coverage

The current test suite covers the main scenarios well. To further improve the test coverage and robustness of the updateSingleSHLinkUseCase, consider adding the following test cases:

  1. Test updating only the passcode (without expiry date).
  2. Test updating only the expiry date (without passcode).
  3. Test with an invalid ID (repo.findOne returns null).
  4. Test with an inactive SHLink (if applicable to your use case).

Here's an example of how you might implement the first suggested test case:

it('should update only the passcode when expiry date is not provided', async () => {
  // Arrange
  const data = { id: '1', passcode: 'newPasscode' };
  repo.findOne.mockResolvedValue(mockEntity);
  repo.update.mockResolvedValue(mockEntity);

  // Act
  const result = await updateSingleSHLinkUseCase(
    { repo, validator: mockValidator },
    data
  );

  // Assert
  expect(repo.findOne).toHaveBeenCalledWith({ id: data.id });
  expect(mockModel.setConfigPasscode).toHaveBeenCalledWith(data.passcode);
  expect(mockModel.setConfigExp).not.toHaveBeenCalled();
  expect(mockValidator).toHaveBeenCalledWith({
    shlink: mockModel,
    passcode: '1234',
  });
  expect(repo.update).toHaveBeenCalledWith(mockEntity);
  expect(result).toBe(mockModel);
});

Adding these test cases will provide more comprehensive coverage of the use case's behavior under different scenarios.

Comment on lines 37 to 53
-- CreateTable
CREATE TABLE "shlink" (
"id" VARCHAR(43) NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMP(3),
"passcode_failures_remaining" INTEGER NOT NULL DEFAULT 5,
"config_passcode" TEXT,
"config_passcode_hash" TEXT,
"config_exp" TIMESTAMP(3),
"active" BOOLEAN NOT NULL DEFAULT true,
"management_token" VARCHAR(43) NOT NULL,
"user_id" VARCHAR(43) NOT NULL,
"name" TEXT NOT NULL DEFAULT 'nameless shlink',

CONSTRAINT "shlink_pkey" PRIMARY KEY ("id")
);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

LGTM! Address security concern with config_passcode storage.

The shlink table creation looks good and aligns with the PR objectives. The timestamp fields, including deleted_at for soft delete, are correctly implemented.

There's a potential security risk with storing both config_passcode and config_passcode_hash. Storing passwords in plain text is generally discouraged. Consider removing the config_passcode field and only keeping the hashed version:

-    "config_passcode" TEXT,
     "config_passcode_hash" TEXT,

This change enhances security by ensuring that plain text passwords are not stored in the database.

Also, consider adding a table comment to explain the purpose of this table and its relationship to other tables.

📝 Committable suggestion

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

Suggested change
-- CreateTable
CREATE TABLE "shlink" (
"id" VARCHAR(43) NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMP(3),
"passcode_failures_remaining" INTEGER NOT NULL DEFAULT 5,
"config_passcode" TEXT,
"config_passcode_hash" TEXT,
"config_exp" TIMESTAMP(3),
"active" BOOLEAN NOT NULL DEFAULT true,
"management_token" VARCHAR(43) NOT NULL,
"user_id" VARCHAR(43) NOT NULL,
"name" TEXT NOT NULL DEFAULT 'nameless shlink',
CONSTRAINT "shlink_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "shlink" (
"id" VARCHAR(43) NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMP(3),
"passcode_failures_remaining" INTEGER NOT NULL DEFAULT 5,
"config_passcode_hash" TEXT,
"config_exp" TIMESTAMP(3),
"active" BOOLEAN NOT NULL DEFAULT true,
"management_token" VARCHAR(43) NOT NULL,
"user_id" VARCHAR(43) NOT NULL,
"name" TEXT NOT NULL DEFAULT 'nameless shlink',
CONSTRAINT "shlink_pkey" PRIMARY KEY ("id")
);
-- Add a comment to explain the purpose of the table
COMMENT ON TABLE "shlink" IS 'Stores information about shortened links and their configurations';

Comment on lines 107 to 162
-- CreateIndex
CREATE UNIQUE INDEX "cas_item_id_key" ON "cas_item"("id");

-- CreateIndex
CREATE UNIQUE INDEX "cas_item_hash_key" ON "cas_item"("hash");

-- CreateIndex
CREATE UNIQUE INDEX "cas_item_content_key" ON "cas_item"("content");

-- CreateIndex
CREATE INDEX "idx_cas_item_hash" ON "cas_item"("id");

-- CreateIndex
CREATE UNIQUE INDEX "shlink_file_id_key" ON "shlink_file"("id");

-- CreateIndex
CREATE INDEX "idx_shlink_file_shlinkId" ON "shlink_file"("shlink_id");

-- CreateIndex
CREATE INDEX "idx_shlink_file_content_hash" ON "shlink_file"("content_hash");

-- CreateIndex
CREATE INDEX "idx_shlink_access_shlinkId" ON "shlink_access"("shlink_id");

-- CreateIndex
CREATE UNIQUE INDEX "shlink_id_key" ON "shlink"("id");

-- CreateIndex
CREATE UNIQUE INDEX "shlink_management_token_key" ON "shlink"("management_token");

-- CreateIndex
CREATE INDEX "idx_shlink_id" ON "shlink"("id");

-- CreateIndex
CREATE UNIQUE INDEX "user_user_id_key" ON "user"("user_id");

-- CreateIndex
CREATE INDEX "idx_user_id" ON "user"("id");

-- CreateIndex
CREATE UNIQUE INDEX "server_config_id_key" ON "server_config"("id");

-- CreateIndex
CREATE INDEX "idx_server_config_id" ON "server_config"("id");

-- CreateIndex
CREATE UNIQUE INDEX "shlink_endpoint_id_key" ON "shlink_endpoint"("id");

-- CreateIndex
CREATE INDEX "idx_shlink_endpoint_shlinkId" ON "shlink_endpoint"("shlink_id");

-- CreateIndex
CREATE INDEX "idx_shlink_endpoint_serverConfigID" ON "shlink_endpoint"("server_config_id");

-- CreateIndex
CREATE INDEX "idx_access_ticket_id" ON "access_ticket"("id");
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Review and optimize indexing strategy.

The index creations generally look good, but there are some potential optimizations:

  1. Remove redundant indexes on primary key columns:

    • cas_item_id_key (line 108)
    • shlink_file_id_key (line 120)
    • shlink_id_key (line 132)
    • server_config_id_key (line 147)
    • shlink_endpoint_id_key (line 153)
    • idx_access_ticket_id (line 162)

    Primary key columns are automatically indexed by the database.

  2. Consider adding a composite index on shlink_access(shlink_id, access_time) if you frequently query access records for a specific shlink within a time range.

  3. Evaluate the need for idx_cas_item_hash (line 117). It seems to be indexing the id column instead of hash. If it's meant to index hash, correct it:

-CREATE INDEX "idx_cas_item_hash" ON "cas_item"("id");
+CREATE INDEX "idx_cas_item_hash" ON "cas_item"("hash");
  1. Consider adding an index on server_config(endpoint_url) if you frequently look up configurations by URL.

Review these suggestions and adjust based on your specific query patterns and performance requirements.

Committable suggestion was skipped due to low confidence.

Comment on lines 67 to 83
-- CreateTable
CREATE TABLE "server_config" (
"id" VARCHAR(43) NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"endpoint_url" TEXT NOT NULL,
"config_key" VARCHAR(43),
"config_client_id" TEXT,
"config_client_secret" TEXT,
"config_client_secret_hash" TEXT,
"config_token_endpoint" TEXT,
"config_refresh_token" TEXT,
"refresh_time" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"access_token_response" TEXT NOT NULL,

CONSTRAINT "server_config_pkey" PRIMARY KEY ("id")
);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

LGTM! Address security concerns and improve default values.

The server_config table creation looks good and aligns with the PR objectives. The timestamp fields are correctly included.

  1. There's a potential security risk with storing both config_client_secret and config_client_secret_hash. Consider removing the config_client_secret field and only keeping the hashed version:
-    "config_client_secret" TEXT,
     "config_client_secret_hash" TEXT,
  1. The default value for refresh_time might not be appropriate. Consider removing the default or setting it to a future time:
-    "refresh_time" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "refresh_time" TIMESTAMP(3) NOT NULL,
  1. Consider encrypting sensitive fields like config_refresh_token and access_token_response.

Also, add a table comment to explain the purpose of this table and its relationship to other tables.

Committable suggestion was skipped due to low confidence.

src/usecases/shlinks/activate-shlink.ts Outdated Show resolved Hide resolved
src/usecases/shlinks/activate-shlink.ts Outdated Show resolved Hide resolved
src/usecases/shlinks/activate-shlink.ts Outdated Show resolved Hide resolved
Copy link

@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

🧹 Outside diff range and nitpick comments (1)
prisma/migrations/20240927144350_test/migration.sql (1)

9-31: LGTM: Consistent timestamp columns added to all remaining tables

The addition of created_at and updated_at columns is correctly implemented and consistent across all remaining tables (server_config, shlink, shlink_access, shlink_endpoint, shlink_file, and user). This change aligns well with the PR objectives and will improve record tracking capabilities throughout the database.

For future migrations involving repetitive changes across multiple tables, consider using a more programmatic approach or a migration tool that supports looping or templating. This could make the migration script more concise and easier to maintain, especially if more tables need to be modified in the future.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between bca4f28 and fcd7927.

📒 Files selected for processing (2)
  • prisma/migrations/20240912115114_initial/migration.sql (1 hunks)
  • prisma/migrations/20240927144350_test/migration.sql (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • prisma/migrations/20240912115114_initial/migration.sql
🔇 Additional comments (3)
prisma/migrations/20240927144350_test/migration.sql (3)

1-3: LGTM: Appropriate timestamp columns added to "access_ticket" table

The addition of created_at and updated_at columns to the "access_ticket" table is well-implemented. These columns will effectively track the creation and last modification times of each record, enhancing data management capabilities.


5-7: LGTM: Timestamp columns correctly added to "cas_item" table

The addition of created_at and updated_at columns to the "cas_item" table is correctly implemented, maintaining consistency with the previous table modifications.


1-31: Consider adding the "deletedAt" column as mentioned in the PR objectives

The migration script successfully adds created_at and updated_at columns to all specified tables, which aligns with part of the PR objectives. However, the PR summary also mentions a deletedAt field, which is not included in this migration.

If the deletedAt column is still part of the requirements, consider adding it to the migration script. This column would typically be defined as a nullable TIMESTAMP to indicate when a record was soft-deleted.

Here's a shell script to verify if deletedAt is used elsewhere in the project:

If the deletedAt column is indeed required, you might want to add it to each table like this:

ADD COLUMN "deleted_at" TIMESTAMP(3);

Please clarify if the deletedAt column should be included in this migration or if it's planned for a separate migration.

Copy link

@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)
prisma/migrations/20240927150538_added_created_updated_dates_to_schema/migration.sql (3)

1-3: LGTM! Consider adding an ON UPDATE clause for the updated_at column.

The addition of created_at and updated_at columns to the access_ticket table is well-implemented. The use of TIMESTAMP(3) provides millisecond precision, which is suitable for most applications. Setting the columns as NOT NULL with a default value of CURRENT_TIMESTAMP ensures data integrity for both existing and new rows.

Consider adding an ON UPDATE CURRENT_TIMESTAMP clause to the updated_at column. This would automatically update the column whenever a row is modified, ensuring that updated_at always reflects the latest change without requiring manual updates in your application code.

Example:

ADD COLUMN "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

5-7: LGTM! Consider the same improvement as suggested for the access_ticket table.

The addition of created_at and updated_at columns to the cas_item table is consistent with the changes made to the access_ticket table and aligns with the PR objectives.

As suggested for the access_ticket table, consider adding an ON UPDATE CURRENT_TIMESTAMP clause to the updated_at column for automatic updates.


9-31: LGTM! Consider the ON UPDATE clause improvement for all remaining tables.

The addition of created_at and updated_at columns is consistent across all remaining tables: server_config, shlink, shlink_access, shlink_endpoint, shlink_file, and user. This consistency is excellent for maintainability and aligns well with the PR objectives.

As suggested earlier, consider adding an ON UPDATE CURRENT_TIMESTAMP clause to the updated_at column for all these tables. This would ensure automatic updates of the updated_at column whenever a row is modified, without requiring manual updates in your application code.

Example for all remaining tables:

ADD COLUMN "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between fcd7927 and 3188f23.

📒 Files selected for processing (1)
  • prisma/migrations/20240927150538_added_created_updated_dates_to_schema/migration.sql (1 hunks)

@godchiSymbionix godchiSymbionix merged commit b518790 into main Sep 27, 2024
3 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.

4 participants