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

fix: raise notice to delete dependent fields after workspace reset #230

Merged

Conversation

JustARatherRidiculouslyLongUsername
Copy link
Contributor

@JustARatherRidiculouslyLongUsername JustARatherRidiculouslyLongUsername commented Dec 10, 2024

Clickup

app.clickup.com

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Enhanced workspace deletion process to manage dependent expense fields.
    • Added user instructions for handling dependent data post-deletion.
  • Bug Fixes

    • Improved handling of deletion logic for workspace-related data.

Copy link

coderabbitai bot commented Dec 10, 2024

Walkthrough

The changes involve modifications to the delete_workspace function in the scripts/sql/reset_db.sql file. A new variable _org_id is introduced to manage the deletion of dependent expense fields associated with a workspace. The function now includes a notice prompting users to switch to the production database for additional deletion tasks. The overall structure remains unchanged, but the added logic enhances dependency management for expense fields.

Changes

File Path Change Summary
scripts/sql/reset_db.sql Modified delete_workspace function to include _org_id for managing dependent expense fields and added user notice for production database operations.

Possibly related PRs

Suggested reviewers

  • ashwin1111
  • ruuushhh

Poem

In the garden where workspaces bloom,
A rabbit hops, dispelling the gloom.
With a flick of the ear, dependencies clear,
Deleting with care, no need for fear.
"Switch to production!" the wise rabbit said,
"For fields of expense, let’s tidy the shed!" 🐰✨


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8a961b5 and def3e25.

📒 Files selected for processing (1)
  • scripts/sql/reset_db.sql (1 hunks)
🔇 Additional comments (3)
scripts/sql/reset_db.sql (3)

198-202: LGTM: Deletion operation follows established patterns

The new deletion operation for expense_attributes_deletion_cache is well-structured and consistent with other delete operations in the function.


205-205: ⚠️ Potential issue

Critical: Move org_id retrieval to beginning of function

The org_id retrieval happens after most deletion operations and just before the workspaces table deletion. This could lead to NULL values if the workspace is deleted before the retrieval.

Move this line to the beginning of the function, right after the variable declarations:

DECLARE
  rcount integer;
  _org_id varchar(255);
BEGIN
+ _org_id := (SELECT org_id FROM workspaces WHERE id = _workspace_id);
  RAISE NOTICE 'Deleting data from workspace % ', _workspace_id;

213-214: ⚠️ Potential issue

Critical: Security and structural improvements needed

While the commands are now on a single line as requested, there are several critical issues to address:

  1. SQL injection vulnerability with string formatting
  2. Unnecessary transaction control statements
  3. Hard-to-read format of the notice

Consider this improved version that addresses all issues:

- RAISE NOTICE E'\n\n\n\n\n\n\n\n\nSwitch to prod db and run the below queries to delete dependent fields';
- RAISE NOTICE E'rollback;begin; delete from platform_schema.dependent_expense_field_mappings where expense_field_id in (select id from platform_schema.expense_fields where org_id =''%'' and type=''DEPENDENT_SELECT''); delete from platform_schema.expense_fields where org_id = ''%'' and type = ''DEPENDENT_SELECT'';\n\n\n\n\n\n\n\n\n\n\n', _org_id, _org_id;
+ RAISE NOTICE E'\nAction Required: Switch to production database and execute the cleanup function:\n';
+ RAISE NOTICE E'SELECT platform_schema.cleanup_dependent_fields(''%'');\n', _org_id;

Create this helper function in the production database:

CREATE OR REPLACE FUNCTION platform_schema.cleanup_dependent_fields(IN _org_id varchar) RETURNS void AS $$
BEGIN
  IF _org_id IS NULL THEN
    RAISE EXCEPTION 'Organization ID cannot be null';
  END IF;

  DELETE FROM platform_schema.dependent_expense_field_mappings 
  WHERE expense_field_id IN (
    SELECT id 
    FROM platform_schema.expense_fields 
    WHERE org_id = _org_id 
    AND type = 'DEPENDENT_SELECT'
  );

  DELETE FROM platform_schema.expense_fields 
  WHERE org_id = _org_id 
  AND type = 'DEPENDENT_SELECT';
END;
$$ LANGUAGE plpgsql;

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

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

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Experiment)
  • @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

PR description must contain a link to a ClickUp (case-insensitive)

Copy link

Tests Skipped Failures Errors Time
157 0 💤 0 ❌ 0 🔥 12.523s ⏱️

Copy link

PR description must contain a link to a ClickUp (case-insensitive)

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

🧹 Outside diff range and nitpick comments (1)
scripts/sql/reset_db.sql (1)

206-208: Improve notice readability and provide context

The notice could be more informative and better formatted:

  1. Explain why these steps need to be run in prod
  2. Consider using a single E'\n' with fewer newlines
  3. Add a warning about the impact of these deletions
- RAISE NOTICE E'\n\n\n\n\n\n\n\n\nSwitch to prod db and run the below queries to delete dependent fields
+ RAISE NOTICE E'\n\n---IMPORTANT---\nThe following cleanup steps must be run in the production database to remove dependent expense fields and their mappings.\nWarning: This will permanently delete field configurations.\n'

Also applies to: 215-215

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 2e6fde4 and 8a961b5.

📒 Files selected for processing (1)
  • scripts/sql/reset_db.sql (1 hunks)
🔇 Additional comments (1)
scripts/sql/reset_db.sql (1)

Line range hint 1-216: Verify deletion order and table coverage

The function deletes data from multiple related tables. Let's verify:

  1. The deletion order respects foreign key constraints
  2. All related tables are included
  3. No orphaned records are left behind
✅ Verification successful

The deletion order in the function appears correct and comprehensive

The delete_workspace function follows a proper deletion order that respects referential integrity:

  1. Starts with dependent tables (errors, export details, summaries) that don't have child references
  2. Proceeds with transaction-related tables (expenses, invoices) and their child records
  3. Handles mapping and settings tables that depend on workspace
  4. Removes credential and attribute tables
  5. Finally cleans up user associations and the workspace itself

The deletion sequence is well-structured to prevent foreign key violations, and the function includes comprehensive logging of deleted records. The additional cleanup of dependent fields in the platform schema is also properly handled.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify table relationships and deletion order

# Find all tables referenced in foreign key constraints
psql -c "\d+" | grep -A1 "Foreign-key constraints:" | grep "REFERENCES" | sort -u

# List all tables in the database for comparison
psql -c "\dt"

# Check for any existing foreign key violations
psql -c "SELECT conname, conrelid::regclass, confrelid::regclass 
         FROM pg_constraint 
         WHERE confrelid::regclass::text LIKE '%workspaces%' 
         OR conrelid::regclass::text LIKE '%workspaces%'"

Length of output: 612


Script:

#!/bin/bash
# Let's analyze the SQL file to understand table relationships through CREATE TABLE statements
# and foreign key declarations

# Search for CREATE TABLE statements
echo "=== Table Definitions ==="
rg "CREATE TABLE" -A 10 --type sql

# Search for FOREIGN KEY constraints
echo -e "\n=== Foreign Key Constraints ==="
rg "FOREIGN KEY" --type sql

# Search for references to workspace_id to ensure we haven't missed any tables
echo -e "\n=== Tables with workspace_id ==="
rg "workspace_id" --type sql | grep -i "create table\|alter table"

Length of output: 354


Script:

#!/bin/bash
# Let's analyze the delete_workspace function implementation to understand the deletion order
# and table dependencies by looking at the file content

echo "=== Analyzing delete_workspace function ==="
cat scripts/sql/reset_db.sql

# Also search for any other SQL files that might contain table definitions
echo -e "\n=== Other SQL files ==="
fd -e sql --type f

Length of output: 6791

Comment on lines 212 to 214
delete from platform_schema.dependent_expense_field_mappings where expense_field_id in (select id from platform_schema.expense_fields where org_id =''%'' and type=''DEPENDENT_SELECT'');

delete from platform_schema.expense_fields where org_id = ''%'' and type = ''DEPENDENT_SELECT'';\n\n\n\n\n\n\n\n\n\n\n', _org_id, _org_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

Security: Fix SQL injection vulnerability and improve architecture

The current implementation has several issues:

  1. Using string formatting for SQL queries is vulnerable to SQL injection
  2. Manual execution in production is error-prone
  3. No validation of _org_id before use

Consider creating a separate function in the production database to handle this cleanup:

CREATE OR REPLACE FUNCTION cleanup_dependent_fields(IN _org_id varchar) RETURNS void AS $$
BEGIN
  IF _org_id IS NULL THEN
    RAISE EXCEPTION 'Organization ID cannot be null';
  END IF;

  DELETE FROM platform_schema.dependent_expense_field_mappings 
  WHERE expense_field_id IN (
    SELECT id 
    FROM platform_schema.expense_fields 
    WHERE org_id = _org_id 
    AND type = 'DEPENDENT_SELECT'
  );

  DELETE FROM platform_schema.expense_fields 
  WHERE org_id = _org_id 
  AND type = 'DEPENDENT_SELECT';
END;
$$ LANGUAGE plpgsql;

Then modify the notice to reference this function:

- delete from platform_schema.dependent_expense_field_mappings where expense_field_id in (select id from platform_schema.expense_fields where org_id =''%'' and type=''DEPENDENT_SELECT'');
- delete from platform_schema.expense_fields where org_id = ''%'' and type = ''DEPENDENT_SELECT'';\n\n\n\n\n\n\n\n\n\n\n'
+ SELECT cleanup_dependent_fields(''%'');\n\n'

Comment on lines 209 to 210
rollback;
begin;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Critical: Remove incorrect transaction control statements

The ROLLBACK statement will undo all the previous deletion operations, and the new BEGIN serves no purpose as it only wraps a NOTICE statement. These statements should be removed.

- rollback;
- begin;

@@ -200,6 +200,20 @@
WHERE w.id = _workspace_id;
GET DIAGNOSTICS rcount = ROW_COUNT;
RAISE NOTICE 'Deleted % workspaces', rcount;

_org_id := (SELECT fyle_org_id FROM workspaces WHERE id = _workspace_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

Critical: Variable assignment will always return NULL

The _org_id assignment happens after the workspaces table has been deleted (see line 202), making this SELECT statement always return NULL. Move this assignment to the beginning of the function, right after the variable declarations.

DECLARE
  rcount integer;
  _org_id varchar(255);
BEGIN
+ _org_id := (SELECT fyle_org_id FROM workspaces WHERE id = _workspace_id);
  RAISE NOTICE 'Deleting data from workspace % ', _workspace_id;

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

Copy link

Tests Skipped Failures Errors Time
157 0 💤 0 ❌ 0 🔥 12.328s ⏱️

* fix: dependent field queries not printing the org id

* fix: delete `expense_attributes_deletion_cache` while workspace reset (#232)
Copy link

Tests Skipped Failures Errors Time
157 0 💤 0 ❌ 0 🔥 12.703s ⏱️

@JustARatherRidiculouslyLongUsername JustARatherRidiculouslyLongUsername merged commit c8b178f into master Dec 13, 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.

2 participants