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: Add created_by, updated_by to conf tables #710

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Ashutosh619-sudo
Copy link
Contributor

@Ashutosh619-sudo Ashutosh619-sudo commented Dec 26, 2024

Description

Please add PR description here, add screenshots if needed

Clickup

Please add link here
https://app.clickup.com/1864988/v/l/6-901605343641-1

Summary by CodeRabbit

Release Notes

  • New Features

    • Added created_by and updated_by fields to various models for tracking user actions.
    • Enhanced serializers and views to include user context during updates.
    • Introduced new mixins for automatic tracking of creation and update timestamps.
  • Bug Fixes

    • Improved validation logic in serializers to ensure required fields are present.
  • Chores

    • Updated dependency version for fyle-accounting-mappings.
    • Modified SQL schema to accommodate new fields.
  • Tests

    • Added test cases and fixtures to support new functionality related to user tracking.

Copy link

coderabbitai bot commented Dec 26, 2024

Walkthrough

This pull request introduces a comprehensive user tracking mechanism across multiple models in the Django application. The changes involve adding created_by and updated_by fields to several models including ExpenseGroupSettings, GeneralMapping, and WorkspaceGeneralSettings. A new AutoAddCreateUpdateInfoMixin is implemented to facilitate automatic tracking of user actions during record creation and updates. The modifications span across models, migrations, serializers, and views to ensure consistent user context preservation throughout the application.

Changes

File Path Change Summary
apps/fyle/migrations/0041_auto_20241226_1155.py Added created_by and updated_by fields to expensegroupsettings model
apps/fyle/models.py Added AutoAddCreateUpdateInfoMixin to ExpenseGroupSettings class
apps/fyle/views.py Updated post method to pass request.user to update_expense_group_settings
apps/mappings/migrations/0011_auto_20241226_1155.py Added created_by and updated_by fields to generalmapping model
apps/workspaces/migrations/0050_auto_20241226_1155.py Added created_by and updated_by fields to WorkspaceGeneralSettings model
requirements.txt Updated fyle-accounting-mappings package from 1.35.0 to 1.36.2
Multiple serializers in apps/workspaces/apis/ Added user context extraction and passing in update methods
Multiple views in apps/workspaces/apis/ Added get_serializer_context method to include request in serializer context

Poem

🐰 Tracking users, hop and bound,
With fields that mark where changes are found
Created by, updated too
A rabbit's trail of data true
Migrations dance, context takes flight! 🌟

Tip

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


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added the size/M Medium PR label Dec 26, 2024
Copy link

Tests Skipped Failures Errors Time
268 0 💤 1 ❌ 0 🔥 59.728s ⏱️

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

🧹 Nitpick comments (7)
tests/test_fyle/fixtures.py (1)

Line range hint 1-4000: Consider adding more edge cases for user tracking

Consider adding test fixtures for the following scenarios:

  1. User updates by different users
  2. Multiple updates tracking history
  3. Invalid user format validation
  4. System-generated updates

Example additions:

'expense_group_settings_response': {
    # ... existing fields ...
+   'created_by': '[email protected]',
+   'updated_by': '[email protected]',
+   'update_history': [
+       {
+           'updated_by': '[email protected]',
+           'updated_at': '2022-01-01T00:00:00Z'
+       },
+       {
+           'updated_by': '[email protected]',
+           'updated_at': '2022-01-02T00:00:00Z'
+       }
+   ]
}
apps/workspaces/apis/map_employees/views.py (1)

12-20: Well-structured approach for passing user context to the serializer.
Providing the full request object in the serializer context is a common and valid approach in Django REST Framework, allowing the serializer to conveniently access the requesting user for created_by or updated_by. However, if only the user is needed, consider storing just the user object (e.g., context['user'] = self.request.user) to keep the context minimal.

apps/fyle/migrations/0041_auto_20241226_1155.py (2)

13-17: Encourage consistent usage of created_by.

The new created_by field will enhance audit logging. Ensure the adding code in your model or manager sets this field on creation. Consider test coverage that checks for non-null created_by in typical creation flows.


18-22: Validate and handle missing updated_by usage.

Similar to created_by, ensure that all update flows properly set updated_by. If the system can't always identify a user (e.g., automated tasks), decide how to handle that scenario to maintain consistent data lineage.

apps/mappings/models.py (1)

7-7: Add a note about the new mixin's functionality.

It's good that this mixin is imported. Consider adding a short docstring or comment in your model to clarify that this mixin handles created_by and updated_by logic automatically, which will help future contributors quickly understand its purpose.

apps/workspaces/apis/export_settings/serializers.py (1)

135-135: Ensure credit card account mapping is user-aware
When creating or updating a MappingSetting for credit card accounts, confirm that the user context is genuinely needed and used. If the user is not essential for certain system-level mappings, consider gracefully handling None.

tests/sql_fixtures/reset_db_fixtures/reset_db.sql (1)

913-915: Consider implementing comprehensive audit logging.

While adding user tracking columns is a good start, consider enhancing the audit trail implementation:

  1. Add timestamp columns (created_at, updated_at) if not already present
  2. Implement audit logging table to track all changes with:
    • Previous and new values
    • Change type (CREATE, UPDATE, DELETE)
    • User context (IP, user agent)
  3. Consider using Django's built-in audit logging capabilities

Would you like me to provide example SQL schema for an audit logging table?

Also applies to: 1110-1112, 1290-1292, 1896-1898

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a284091 and 1731dda.

📒 Files selected for processing (20)
  • apps/fyle/migrations/0041_auto_20241226_1155.py (1 hunks)
  • apps/fyle/models.py (4 hunks)
  • apps/fyle/views.py (1 hunks)
  • apps/mappings/migrations/0011_auto_20241226_1155.py (1 hunks)
  • apps/mappings/models.py (1 hunks)
  • apps/workspaces/apis/advanced_configurations/serializers.py (2 hunks)
  • apps/workspaces/apis/advanced_configurations/views.py (1 hunks)
  • apps/workspaces/apis/export_settings/serializers.py (4 hunks)
  • apps/workspaces/apis/export_settings/views.py (1 hunks)
  • apps/workspaces/apis/import_settings/serializers.py (3 hunks)
  • apps/workspaces/apis/import_settings/views.py (1 hunks)
  • apps/workspaces/apis/map_employees/serializers.py (2 hunks)
  • apps/workspaces/apis/map_employees/views.py (1 hunks)
  • apps/workspaces/migrations/0050_auto_20241226_1155.py (1 hunks)
  • apps/workspaces/models.py (2 hunks)
  • requirements.txt (1 hunks)
  • tests/sql_fixtures/reset_db_fixtures/reset_db.sql (10 hunks)
  • tests/test_fyle/fixtures.py (1 hunks)
  • tests/test_fyle/test_models.py (1 hunks)
  • tests/test_workspaces/fixtures.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • requirements.txt
🔇 Additional comments (33)
tests/test_fyle/fixtures.py (3)

3163-3164: Add user tracking fields to expense group settings response

The expense group settings response has been updated to include created_by and updated_by fields, which aligns with the PR objective of enhancing user tracking capabilities.


Line range hint 1-3162: LGTM: Test fixtures look comprehensive and well-structured

The test fixtures provide good coverage for testing various scenarios:

  1. Raw expense data with detailed fields
  2. Default raw expense with essential fields
  3. Multiple expense scenarios (spent_at, refunds, etc.)
  4. Corporate card expenses with different bank transaction ID cases
  5. Expense group responses with various states
  6. Custom field configurations
  7. Employee, category, and cost center data

The data structure is consistent and includes all necessary fields for testing the user tracking enhancements.

Also applies to: 3165-4000


Line range hint 1-4000: Verify test coverage for user tracking fields

While the fixtures include the new user tracking fields, we should verify that there are sufficient test cases covering:

  1. Creation of new records with user context
  2. Updates to existing records with user context
  3. Edge cases like null/empty user values
  4. Validation of user field formats
apps/workspaces/apis/export_settings/views.py (1)

12-20: Consistent inclusion of request in serializer context for user tracking.
Similar to the MapEmployeesView, passing the request object here is beneficial for extracting the user in the serializer. This consistency across views ensures straightforward maintenance and audit of user-based changes.

apps/workspaces/apis/advanced_configurations/views.py (1)

12-20: Provides a unified pattern for user context availability.
By adding context['request'] = self.request, all update operations that require user information will remain consistent with other parts of the codebase. This pattern supports improved traceability for updates.

apps/mappings/migrations/0011_auto_20241226_1155.py (1)

12-23: Fields added for auditability and traceability.
Adding created_by and updated_by as nullable CharFields is a straightforward solution for capturing user data. Consider these points for long-term maintainability:
• Ensure that 255 characters suffice for storing user identifiers such as emails.
• Validate whether indexing is needed if queries based on these fields become frequent.
• If the user base grows or if verifying references is required, you may want to store a foreign key in the future.

apps/workspaces/migrations/0050_auto_20241226_1155.py (2)

13-17: Ensure the created_by field is consistently populated.

It's good that created_by is nullable and can be blank, but make sure all code paths consistently set this field at creation time. If a user context isn't available, consider documenting or defaulting behavior to maintain data integrity.


18-22: Confirm update logic for updated_by usage.

updated_by is designed to track the last user who updated the record. Verify that the model or resource layer automatically sets this field whenever a record is updated. If not, it may lead to missing user data for certain update paths.
[approve]

apps/workspaces/apis/import_settings/views.py (1)

14-21: Great addition for user context in serializer.

Exposing the request through get_serializer_context is a clean approach. Make sure your serializers handle edge cases where the request might be absent (e.g., background tasks without an HTTP context).

apps/workspaces/apis/map_employees/serializers.py (2)

26-28: Gracefully handle request or user absence.

When request or user is missing, you fall back to None. Make sure your logic downstream can handle None for user (e.g., logging or validations).


39-40: User parameter now passed to update_or_create.

This aligns with the new auditing requirements. Confirm that update_or_create properly consumes user and sets updated_by. If user is None, confirm you have fallback behavior.

apps/mappings/models.py (1)

10-10: Validate user assignment when records are created or updated.

While inheriting from AutoAddCreateUpdateInfoMixin adds fields for created_by and updated_by, ensure the user object is consistently available at all model creation or update call sites so that these fields are populated correctly.

apps/workspaces/apis/advanced_configurations/serializers.py (2)

69-71: Ensure the user context can't be None when needed.

Checking request.user is helpful, but if the user is None, the tracking fields won’t be correctly populated. If there's a scenario where the user might not be logged in, handle it explicitly.


87-87: Great approach to capturing the user context.

Passing user to both WorkspaceGeneralSettings.objects.update_or_create(...) and GeneralMapping.objects.update_or_create(...) ensures accurate tracking of created_by and updated_by. Just confirm these calls fail gracefully when no user is provided.

Also applies to: 90-90

apps/fyle/views.py (1)

86-86: Consistent user tracing.

Including request.user when updating ExpenseGroupSettings aligns with the newly introduced fields. Ensure request authentication is mandatory here so request.user is never undefined.

tests/test_workspaces/fixtures.py (1)

77-78: Good coverage with test fixtures.

Including created_by and updated_by in these fixtures helps validate user tracking logic. Consider adding test assertions that verify these fields are accurately set and retrieved.

apps/workspaces/apis/import_settings/serializers.py (4)

81-83: Ensure robust handling of the user in the request context
The logic for retrieving user from request looks correct, but note that request or user might be None for certain background processes or automated tasks. Consider graceful handling or fallback defaults if user is not found.


110-110: Confirm existence of updated manager or model method
Passing user=user to WorkspaceGeneralSettings.objects.update_or_create() implies that your model manager or the update_or_create method supports a user parameter. Ensure the underlying logic consumes this parameter as intended and handles edge cases (e.g., user is None).


113-113: Check consistent usage of user parameter across all calls
Similar to the previous comment, confirm that GeneralMapping.objects.update_or_create(..., user=user) is fully implemented. If the user parameter is optional, add safe handling.


136-136: Review iteration-based updates
Here, user=user is also passed within a loop. Verify that, for each MappingSetting update, passing the same user is correct, especially if any user-based logic might differ across individual records.

apps/workspaces/apis/export_settings/serializers.py (4)

96-98: Retrieve user from request for export settings
Your approach to extracting the user is consistent with the import settings serializer. Just be sure to handle fallback logic if request.user is unset.


127-127: Confirm user parameter usage in update_or_create
Passing user suggests you have a custom manager or method that records this information. Confirm that the logic handles null or unknown users without errors.


158-158: Validate optional user passing to ExpenseGroupSettings.update_expense_group_settings
Ensure the newly added user parameter is consistently utilized or handle the case when user is None.


176-176: Extend user auditing to general mappings
Similar to the above methods, confirm the logic in GeneralMapping.objects.update_or_create(..., user=user) is well-tested and handles all edge cases.

apps/workspaces/models.py (2)

10-11: New mixin import
By importing and using AutoAddCreateUpdateInfoMixin, you add automatic tracking for creation and update metadata. This import is correct if the mixin logic is tested and aligns with your auditing requirements.


95-95: Inheritance from AutoAddCreateUpdateInfoMixin
Mixing AutoAddCreateUpdateInfoMixin and models.Model ensures WorkspaceGeneralSettings includes required auditing fields or methods. Confirm that existing migrations and DB schema are compatible with the new fields.

apps/fyle/models.py (4)

206-206: Appropriate class extension.

Inheriting from AutoAddCreateUpdateInfoMixin here correctly integrates the new user tracking fields (created_by, updated_by). This is aligned with the PR objective to enhance auditability. The usage looks good.


306-306: Confirm user assignment in update_or_create.

The signature implies that user will be stored in your custom mixin fields (created_by, updated_by). Double-check that the mixin’s save() method properly sets these fields, and confirm that no override is needed for the update_or_create usage.

Do you want me to examine the mixin’s implementation or open a GitHub issue to verify proper usage of created_by and updated_by?


230-230: Validate the user parameter usage.

Ensure that passing user into update_expense_group_settings is always possible from the various call sites. If request.user can be anonymous in any scenario, consider fallback logic or explicitly ensure authentication is required.

✅ Verification successful

Let me verify the authentication mechanisms in the views and APIs where this function is called.


Let me check the specific authentication setup in the views file.


Let me check the specific view class that handles expense group settings.


Let me check one final thing about the base class and middleware setup.


Let me check the Django settings in the correct location.


Let me check the actual content of the main settings file and any middleware configuration.


The user parameter is properly secured in update_expense_group_settings

Based on the verification results:

  1. The application has global authentication configured in settings.py:
    REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticated', 'apps.workspaces.permissions.WorkspacePermissions'),
        'DEFAULT_AUTHENTICATION_CLASSES': ('fyle_rest_auth.authentication.FyleJWTAuthentication',)
    }
  2. The ExpenseGroupSettingsView inherits from generics.ListCreateAPIView and is protected by the global authentication middleware.
  3. All call sites pass either request.user or an authenticated user object.

The user parameter is properly secured through Django's authentication system and workspace permissions, ensuring that anonymous users cannot access this functionality.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all function calls to update_expense_group_settings provide a non-null user.

rg -A2 $'update_expense_group_settings\\('

Length of output: 1210


Script:

#!/bin/bash
# Check authentication decorators and base classes in the relevant views
ast-grep --pattern 'class $class_name($$base_classes):
  $$$
  def $method($params) {
    $$$
    update_expense_group_settings($$$)
    $$$
  }' apps/fyle/views.py apps/workspaces/apis/export_settings/serializers.py

# Also check for authentication middleware and permissions
rg -l "permission_classes|IsAuthenticated|authentication_classes" apps/fyle/views.py apps/workspaces/apis/export_settings/views.py

Length of output: 370


Script:

#!/bin/bash
# Check the specific authentication and permission setup in views.py
rg -B2 -A2 "permission_classes|IsAuthenticated|authentication_classes" apps/fyle/views.py

# Also check the base view class for the expense group settings
ast-grep --pattern 'class ExpenseGroupSettings$_($base):
  $$$' apps/fyle/views.py

Length of output: 291


Script:

#!/bin/bash
# Find the view class that handles expense group settings
rg -B3 -A3 "class.*ExpenseGroupSettings.*View" apps/fyle/views.py

# Also check the URLs to see the view registration
rg "ExpenseGroupSettings.*View" apps/fyle/urls.py

Length of output: 414


Script:

#!/bin/bash
# Check the content of the ExpenseGroupSettingsView class
rg -B5 -A10 "class ExpenseGroupSettingsView" apps/fyle/views.py

# Also check for any global authentication middleware in settings
rg -l "REST_FRAMEWORK.*authentication" apps/fyle/settings.py apps/fyle/default_settings.py

Length of output: 853


Script:

#!/bin/bash
# Find Django settings files
fd settings.py

# Once found, check for REST_FRAMEWORK authentication settings
rg -l "REST_FRAMEWORK.*authentication" $(fd settings.py)

Length of output: 407


Script:

#!/bin/bash
# Check the main settings file for authentication configuration
rg -A5 "REST_FRAMEWORK|MIDDLEWARE" fyle_qbo_api/settings.py

# Also check if there's any authentication middleware in the base class
rg -A3 "class.*ListCreateAPIView" $(fd -t f -e py)

Length of output: 18487


16-16: Confirm the import path is correct.

Ensure that fyle_accounting_mappings.mixins indeed defines AutoAddCreateUpdateInfoMixin. This avoids potential ImportError or AttributeError if the path is incorrect or the mixin does not exist in that module.

tests/sql_fixtures/reset_db_fixtures/reset_db.sql (3)

33272-33277: Data migration strategy looks appropriate.

The data migration approach is correct:

  1. Existing records are initialized with NULL values for new tracking columns
  2. This maintains data integrity while allowing future records to capture user information

Also applies to: 33495-33500, 33543-33559, 33924-33929


34031-34031: Sequence update is correct.

The sequence value update to 205 properly accounts for the four new migrations (202-205) that add the user tracking columns.


913-915: Schema changes look good but verify foreign key constraints.

The addition of created_by and updated_by columns is consistent across tables. However, since these columns likely reference user IDs, consider:

  1. Adding foreign key constraints to the user table
  2. Adding indexes for query performance

Let's check if there are any foreign key constraints on user-related columns in other tables:

Also applies to: 1110-1112, 1290-1292, 1896-1898

Comment on lines +41 to +43
user = Workspace.objects.get(id=1).user

ExpenseGroupSettings.update_expense_group_settings(payload, 98)
ExpenseGroupSettings.update_expense_group_settings(payload, 98, user)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ensure Workspace.objects.get(id=1).user returns a valid user object
Since Workspace.user is a many-to-many field, Workspace.objects.get(id=1).user may return a related manager or queryset rather than a single user. Make sure you fetch the correct user or handle multiple users if the workspace can have more than one.

-    user = Workspace.objects.get(id=1).user
+    user = Workspace.objects.get(id=1).user.first()  # or handle multiple users

Committable suggestion skipped: line range outside the PR's diff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size/M Medium PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants