Skip to content

Comments

Fix/added property type prop deployment ts error#6856

Closed
naman-agrawal-shipsy wants to merge 193 commits intomakeplane:previewfrom
shipsy:fix/added-property-type-prop--deployment-ts-error
Closed

Fix/added property type prop deployment ts error#6856
naman-agrawal-shipsy wants to merge 193 commits intomakeplane:previewfrom
shipsy:fix/added-property-type-prop--deployment-ts-error

Conversation

@naman-agrawal-shipsy
Copy link

@naman-agrawal-shipsy naman-agrawal-shipsy commented Apr 1, 2025

Description

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring
  • Performance improvements
  • Documentation update

Screenshots and Media (if applicable)

Test Scenarios

References

Summary by CodeRabbit

  • New Features

    • Enhanced issue tracking with additional custom fields now visible across issue details, spreadsheets, and filters.
    • New global search functionality to quickly navigate workspaces and projects.
    • Expanded time tracking available to all users.
  • Improvements

    • Streamlined UI by removing legacy help menus and redundant upgrade options.
    • Updated server and deployment configurations for smoother performance and larger file uploads.
    • Improved sign-out handling for a more responsive user experience.

abu-b-sidq and others added 27 commits March 22, 2025 11:42
Changes to support multipart data in nginx config files
…rnames

Filter the issues with usernames from headers( X-Assume-Role)
Fix for filteting the issues by type_id
Added four new fileds to issue model and added filteration
…perties

added new fileds to display properties
…perties

Dr iss 266189 addednewto display properties
…-in-properties

Added 4 additional properties (names) in fixed issue properties
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 1, 2025

Walkthrough

This pull request introduces extensive enhancements and refactoring across backend, frontend, deployment, and configuration files. Major changes include new Docker commands and CMD instructions, expanded API endpoints with custom property handling, updates to serializers, URL routing, and view logic. Multiple Django migrations adjust the database schema for issue and project custom properties. The codebase also receives numerous updates to React components and filtering functionality along with adjustments in permissions, authentication flows, CI/CD pipelines, and configuration files.

Changes

File(s) Change Summary
Dockerfiles
(admin/Dockerfile.admin, apiserver/Dockerfile.api, web/Dockerfile.web)
Added CMD instructions for container startup, exposed ports, build argument for env file, and Flower monitoring installation.
API Endpoints & Serializers
(apiserver/plane/api/serializers/, apiserver/plane/api/views/, apiserver/plane/api/urls/*)
Introduced new endpoints and serializers for handling issue custom properties, webhook operations, and enhanced filtering; updated URL patterns and view control flow based on environment types.
Authentication & Permissions
(apiserver/plane/authentication/, apiserver/plane/app/permissions/)
Modified token validation with role assumption, updated magic code flows, added helper methods for user creation, and expanded permissions to include guest roles.
Database Migrations
(apiserver/plane/db/migrations/0084–0091_*.py)
Added new models (IssueCustomProperty, IssueTypeCustomProperty), modified field types and constraints, removed outdated associations, and updated unique constraints.
Configurations & Settings
(aio/nginx.conf, nginx/, supervisord.conf, settings/, redis.py, storage.py)
Added new Nginx directives, updated storage and session settings, added environment variable loading, and introduced debug print statements.
CI/CD & Deployment
(demo.Jenkinsfile, docker-compose*.yml, deploy/selfhost/install.sh)
Introduced a new Jenkins pipeline for demo deployments, updated Docker Compose configurations by removing services and adding new port mappings, and modified repository URL for custom builds.
Web UI & Frontend Components
(web/app/, web/core/components/, space/*)
Added new React components and hooks for custom property display/editing, updated filter components and layout logic, and removed legacy GitHub links and sidebar options.
Utility & Type Updates
(packages/types/src/, web/core/constants/, web/core/services/workspace.service.ts, issue_filters.py)
Extended type definitions, added new constants and filtering functions for issue properties, and updated utility functions for grouping and custom property mapping.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant APIView as IssueCustomPropertyUpdateAPIView
    participant Serializer
    participant DB
    Client->>APIView: Send PATCH request with custom property data
    APIView->>Serializer: Validate and process request
    Serializer->>DB: Update Issue & Custom Property records
    DB-->>Serializer: Return updated records
    Serializer-->>APIView: Serialize updated response
    APIView-->>Client: Return success response
Loading

Possibly related PRs

  • chore: properties validation. #5718: Introduced a new property isDisabled in issue properties, focusing on enhanced property interactivity and validation which aligns with the custom properties handling in this PR.

Suggested reviewers

  • SatishGandham

Poem

In the code forest, I hop with delight,
Tracking custom properties deep into the night.
Endpoints and migrations gracefully align,
With Docker and settings all perfectly fine.
My little paws skip on refactor trails so free,
Debugging each bug with a joyful spree.
Hop on and celebrate—code blooms like a tree! 🐇

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 42

🔭 Outside diff range comments (4)
web/core/components/workspace/sidebar/help-section.tsx (1)

31-32: 💡 Verification agent

🧩 Analysis chain

Verify used hooks and state.

With the removal of the help menu functionality, check if isIntercomToggle, toggleIntercom, canUseLocalDB, and toggleLocalDB hooks are still needed in this component.


🏁 Script executed:

#!/bin/bash
# Search for references to these hooks and state in this file
# to verify if they're still used after the changes

rg -A 3 "toggleIntercom|isIntercomToggle|canUseLocalDB|toggleLocalDB" web/core/components/workspace/sidebar/help-section.tsx

Length of output: 488


Action: Remove Unused LocalDB Hooks

After verifying the code, it appears that while the intercom hooks (isIntercomToggle and toggleIntercom) are actively used (e.g., in the toggleIntercom(!isIntercomToggle) call), the localDB hooks (canUseLocalDB and toggleLocalDB) are destructured but not used anywhere in the component. Please verify if these localDB hooks are intended for future use. If not, removing them will clean up the code.

  • File: web/core/components/workspace/sidebar/help-section.tsx
  • Location: Lines 31-32 and their usage below
  • Suggestion: Remove the destructuring of canUseLocalDB and toggleLocalDB from useUserSettings if they are no longer needed.
apiserver/plane/app/permissions/project.py (1)

119-153: 🛠️ Refactor suggestion

Consider unifying with ProjectEntityPermission.

This entire new class duplicates much permission logic. Factor shared logic into a helper or base class to avoid repeated code and reduce the chance of drift.

apiserver/plane/app/views/view/base.py (1)

209-306: 💡 Verification agent

🧩 Analysis chain

Method signature change requires careful integration.

The method signature has changed from def get_queryset(self) to def get_queryset(self, filters), which could break backward compatibility if this method is called elsewhere without the new parameter.

Also, the custom properties filtering implementation looks good, but make sure all callers provide the required filters parameter.


🏁 Script executed:

#!/bin/bash
# Search for any direct calls to get_queryset in this class that might not pass the filters parameter
rg "\.get_queryset\(\)" --type py | grep -v "super\(\)"

Length of output: 8721


Action Required: Address Backward Compatibility for get_queryset Signature Change

The change of the method signature from def get_queryset(self) to def get_queryset(self, filters) introduces a potential backward compatibility issue. The shell script output shows many call sites across the repository (e.g., in modules under apiserver/plane/space/views, apiserver/plane/api/views, etc.) that still invoke .get_queryset() without supplying the required filters parameter. This will likely lead to runtime errors.

Recommendations:

  • Update Call Sites: Go through the identified files and update all calls to .get_queryset() by providing the appropriate filters (e.g., an empty dictionary {} when no filters are needed).
  • Consider a Fallback: If it's desirable for backward compatibility, consider modifying the method signature to include a default value (e.g., def get_queryset(self, filters={})), ensuring that all existing usages remain functional.
apiserver/plane/api/views/search.py (1)

236-275: 🛠️ Refactor suggestion

Ensure broader coverage in global search.

Currently, the MODELS_MAPPER only has "issue" active while others are commented out. For true global search, consider uncommenting and supporting those entity filters. Also, retrieving created_by_username from request headers may be unconventional—query parameters might be more standard and explicit.

🧹 Nitpick comments (95)
web/app/provider.tsx (4)

54-54: Remove console logging before pushing to production.

This debug statement should be removed before the code is deployed to production, as it leaks information about user navigation and decreases performance.

-    console.log(pathname, 'pathname');

60-60: Remove console logging before pushing to production.

This debug statement should be removed before the code is deployed to production, as it could leak sensitive information and impact performance.

-      console.log('onIncomingMessage', event);

65-65: Improve error handling in the catch block.

The current implementation has an empty catch block which silently swallows errors. This may make debugging difficult in the future.

-        } catch (err) {}
+        } catch (err) {
+          console.error("Error during sign out:", err);
+          window.parent.postMessage({ type: "PLANE_SIGN_OUT_ERROR", error: err.message }, trustedOrigin);
+        }

72-72: Update useEffect dependencies.

The effect depends on pathname and handleSignOut but they're not included in the dependency array. This could cause stale values to be used if these values change.

-  }, []);
+  }, [pathname, handleSignOut]);
web/core/components/workspace/sidebar/help-section.tsx (5)

6-8: Remove unused imports.

After removing the CustomMenu component and its associated menu items, several imports are no longer used in this file:

  • FileText, HelpCircle, MessagesSquare, User from lucide-react
  • CustomMenu from @plane/ui

Consider removing these unused imports to keep the codebase clean.

-import { FileText, HelpCircle, MessagesSquare, MoveLeft, User } from "lucide-react";
+import { MoveLeft } from "lucide-react";
// ui
-import { CustomMenu, Tooltip, ToggleSwitch } from "@plane/ui";
+import { Tooltip } from "@plane/ui";

34-35: Remove unused state variables.

The state variables isNeedHelpOpen and isChangeLogOpen appear to be unused or partially unused after removing the help menu functionality. The isChangeLogOpen is still used for the ProductUpdatesModal, but isNeedHelpOpen doesn't seem to be used anywhere now.

// states
-  const [isNeedHelpOpen, setIsNeedHelpOpen] = useState(false);
  const [isChangeLogOpen, setIsChangeLogOpen] = useState(false);

37-39: Remove unused function.

The handleCrispWindowShow function is no longer used after removing the help menu functionality. Consider removing it to improve code maintainability.

-  const handleCrispWindowShow = () => {
-    toggleIntercom(!isIntercomToggle);
-  };

54-56: Justify UI layout change.

The layout has been adjusted to use justify-end ml-auto instead of the previous spacing distribution. This aligns the collapse button to the right side of the sidebar when not collapsed.

While this change is valid, consider documenting the reason for this UI adjustment, especially since it changes the visual layout of a component that users interact with frequently.


43-72: Consider alternatives for removed help functionality.

The removal of the help menu items reduces the accessibility of important resources like documentation, support messaging, and keyboard shortcuts. Consider adding an alternative way for users to access these resources, perhaps through a main navigation item or a different UI component.

apiserver/plane/api/urls/search.py (1)

8-12: URL pattern name doesn't match endpoint purpose.

The URL pattern for the search endpoint is named "project", which doesn't reflect its actual functionality. A more descriptive name like "global_search" would improve clarity and maintainability.

 path(
     "workspaces/<str:slug>/search/",
     GlobalSearchEndpoint.as_view(),
-    name="project",
+    name="global_search",
 ),
apiserver/plane/db/migrations/0085_remove_issuecustomproperty_project_custom_property_and_more.py (2)

19-21: Fix spelling error in related_name parameter

There's a spelling error in the related_name parameter: "custom_propery_issue_type" should be "custom_property_issue_type".

-            field=models.ManyToManyField(related_name='custom_propery_issue_type', to='db.issuetype'),
+            field=models.ManyToManyField(related_name='custom_property_issue_type', to='db.issuetype'),

6-22: Consider consolidating related migrations

This migration appears to be the first in a sequence of 6 migrations (0085-0090) that make related changes to the same models. From the context provided, the subsequent migrations rename fields, correct spelling errors, and make additional changes to the same models modified here.

For cleaner schema evolution and easier maintenance, consider consolidating these related migrations into fewer, more comprehensive migrations. This helps reduce the complexity and potential issues when applying migrations in different environments.

apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (1)

14-18: New field addition looks good, but be aware of subsequent migrations

The addition of the issue_type foreign key field to the issuecustomproperty model with appropriate null and blank settings is well implemented. However, note that subsequent migrations (0088-0090) show this field will undergo multiple revisions - first changing its reference from issuetype to issuetypecustomproperty and then renaming it.

Consider consolidating these sequential migrations into a single migration before merging to production to minimize migration overhead.

web/core/hooks/use-group-dragndrop.ts (1)

64-65: Good fix for type consistency in key checks

Converting moduleKey and cycleKey to strings before checking for inclusion in the data keys is a good practice that prevents type mismatch issues. This change ensures consistent comparison behavior regardless of key types.

Consider adding a comment explaining why the toString() conversion is necessary for future maintainers. Also, for better type safety, you could further refine this with more explicit type checks:

-const isModuleChanged = Object.keys(data).includes(moduleKey.toString());
-const isCycleChanged = Object.keys(data).includes(cycleKey.toString());
+// Convert keys to strings to ensure consistent type comparison
+const moduleKeyString = moduleKey.toString();
+const cycleKeyString = cycleKey.toString();
+const isModuleChanged = Object.keys(data).includes(moduleKeyString);
+const isCycleChanged = Object.keys(data).includes(cycleKeyString);
apiserver/plane/api/views/attachment.py (2)

9-9: Remove unused import.

According to static analysis, allow_permission is imported but never used. Removing it will clean up the code.

-from plane.app.permissions import ProjectEntityPermission, allow_permission
+from plane.app.permissions import ProjectEntityPermission
🧰 Tools
🪛 Ruff (0.8.2)

9-9: plane.app.permissions.allow_permission imported but unused

Remove unused import: plane.app.permissions.allow_permission

(F401)


167-169: Reevaluate overwriting 'created_by' on patch.

When marking the attachment as uploaded, you're setting created_by to the current user, potentially overwriting the original creator. Consider using a separate field, such as uploaded_by or relying on updated_by to track this action more accurately.

apiserver/plane/authentication/utils/redirection_path.py (1)

9-10:

Details

❓ Verification inconclusive

Verify onboarding bypass implications

By commenting out these lines, users will no longer be redirected to the onboarding path even if they haven't completed onboarding. Ensure this change is intentional and won't cause issues with user experience or data setup.


🏁 Script executed:

#!/bin/bash
# Check if there are other places in the codebase that might depend on this onboarding redirection
echo "Searching for code that references onboarding redirection..."
rg -A 3 "profile.is_onboarded" --type py
rg -A 3 "return \"onboarding\"" --type py

Length of output: 2225


Action: Verify Onboarding Redirection Behavior

The redirection logic in apiserver/plane/authentication/utils/redirection_path.py has been disabled by commenting out the following lines:

    # if not profile.is_onboarded:
    #     return "onboarding"

Our search confirms that the profile.is_onboarded flag is still actively used in other parts of the code (e.g., in apiserver/plane/app/views/user/base.py, apiserver/plane/authentication/views/app/magic.py, and apiserver/plane/api/views/member.py). This indicates that while user onboarding status is maintained and updated, the automatic redirection to the onboarding flow is now bypassed.

Please verify that:

  • This change is intentional and consistent with the revised onboarding flow.
  • Users who have not completed onboarding are handled appropriately within the updated process.
  • There are no unintended impacts on user experience or data setup due to the removal of this redirection.

If the bypass is by design, consider updating comments or documentation to clarify the intentional behavior change.

apiserver/plane/app/urls/views.py (1)

66-74: Consider using a unique name for this URL pattern

The new endpoint for retrieving workspace custom properties is using the same name ('global-view-issues') as the existing endpoint on line 64. This could cause issues with Django's reverse URL lookup functionality.

 path(
     "workspaces/<str:slug>/custom-properties/",
     WorkspaceViewIssuesViewSet.as_view(
         {
             "get": "listCustomProperty",
         }
     ),
-    name="global-view-issues",
+    name="global-view-custom-properties",
 ),
apiserver/plane/api/serializers/project.py (1)

12-12: Remove unused import

The IssueTypeSerializer is imported but not used anywhere in this file.

-from .issue_type import IssueTypeSerializer
🧰 Tools
🪛 Ruff (0.8.2)

12-12: .issue_type.IssueTypeSerializer imported but unused

Remove unused import: .issue_type.IssueTypeSerializer

(F401)

apiserver/plane/app/urls/issue.py (2)

325-329: URL path missing trailing slash and using inconsistent project_id type.

The search endpoint URL is missing a trailing slash, which is inconsistent with other endpoints in this file. Also, this endpoint uses <str:project_id> while most other endpoints use <uuid:project_id>.

-    path(
-        "workspaces/<str:slug>/projects/<str:project_id>/search",
-        SearchAPIEndpoint.as_view(),
-        name="key-codes",
-    ),
+    path(
+        "workspaces/<str:slug>/projects/<str:project_id>/search/",
+        SearchAPIEndpoint.as_view(),
+        name="search-issues",
+    ),

330-334: URL path name may contain typo and uses inconsistent naming.

The endpoint name "filed_search" might contain a typo (should be "field_search"?). Also, the name parameter "key-codes" doesn't seem to accurately describe the search functionality and is reused from the previous endpoint.

-    path(
-        "workspaces/<str:slug>/projects/<str:project_id>/filed_search",
-        SearchSingleValueAPI.as_view(),
-        name="key-codes"
-    )
+    path(
+        "workspaces/<str:slug>/projects/<str:project_id>/field_search/",
+        SearchSingleValueAPI.as_view(),
+        name="field-search"
+    )
apiserver/plane/db/models/base.py (2)

36-38: Good conditional check for created_by field.

The added condition prevents overwriting an existing created_by value when saving an instance, which is a good improvement. However, there's some inconsistent indentation and an unnecessary blank line.

-                if self.created_by is None:
-                    self.created_by = user
-                    
+                if self.created_by is None:
+                    self.created_by = user

46-48: Remove unnecessary blank lines at end of file.

There are multiple blank lines at the end of the file which aren't necessary.

-
-
-    
+
space/core/components/issues/filters/selection.tsx (1)

9-9: Consider removing unused import if not needed immediately.

The FilterCustomProperty component is imported but not used in this file. This might be intentional for future implementation, but consider removing it if not needed immediately to avoid increasing bundle size.

-import { FilterPriority, FilterState, FilterCustomProperty } from ".";
+import { FilterPriority, FilterState } from ".";
apiserver/plane/db/models/__init__.py (1)

44-44: Address unused imports flagged by static analysis.

The imports for IssueCustomProperty and IssueTypeCustomProperty are flagged as unused by static analysis. For __init__.py files, imports typically serve to re-export symbols for easier access by other modules.

To fix the linting warnings, you can either:

  1. Add the imports to __all__ variable:
+__all__ = [
+    # ... other imports
+    "IssueCustomProperty",
+    "IssueTypeCustomProperty",
+    # ... other imports
+]
  1. Or use a redundant alias to acknowledge the purposeful re-export:
-from .issue import (
+from .issue import (  # noqa
     # ... other imports
     IssueCustomProperty
)

-from .issue_type import IssueType, IssueTypeCustomProperty
+from .issue_type import IssueType, IssueTypeCustomProperty  # noqa

Also applies to: 115-115

🧰 Tools
🪛 Ruff (0.8.2)

44-44: .issue.IssueCustomProperty imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

web/core/components/issues/issue-layouts/spreadsheet/columns/standard-property-column.tsx (1)

1-22: Component structure looks good, but consider type safety improvements.

The component correctly renders standard properties from issue objects in a spreadsheet layout. The use of conditional rendering with optional chaining is appropriate.

Consider adding better handling for complex property values and improving type safety:

import React from "react";
import { observer } from "mobx-react";
// types
import { TIssue } from "@plane/types";
import { Row, Tooltip } from "@plane/ui";

type Props = {
  issue: TIssue;
-  property: string;
+  property: keyof TIssue;
};

export const SpreadsheetStandardPropertyColumn: React.FC<Props> = observer((props) => {
  const { issue, property } = props;

+  // Helper to format property value for display
+  const getFormattedValue = () => {
+    const value = issue?.[property];
+    if (value === null || value === undefined) return "";
+    if (typeof value === "object") return JSON.stringify(value);
+    return String(value);
+  };
+
+  const displayValue = getFormattedValue();

  return (
-    <Tooltip tooltipContent={issue?.[property]} disabled={!issue?.[property]}>
+    <Tooltip tooltipContent={displayValue} disabled={!displayValue}>
      <Row className="h-11 truncate border-b-[0.5px] border-custom-border-200 pt-[1.25em] text-xs hover:bg-custom-background-80">
-          {issue?.[property]}
+          {displayValue}
      </Row>
    </Tooltip>
  );
});
apiserver/plane/db/migrations/0091_issue_customer_code_issue_hub_code_and_more.py (1)

13-42: Consider adding indexes for frequent lookups.

Each new field is configured with blank=True, null=True. If you plan to filter or query issues by any of these codes, adding a database index can enhance performance.

To add an index, apply a similar patch to each added field:

 migrations.AddField(
     model_name='issue',
     name='customer_code',
-    field=models.CharField(blank=True, max_length=255, null=True),
+    field=models.CharField(db_index=True, blank=True, max_length=255, null=True),
 ),
apiserver/plane/api/urls/__init__.py (1)

9-10: Fix spelling of imported and expanded patterns.

The variable name "patters" appears to be a typo. Correcting it to "patterns" improves clarity and consistency.

Apply the following diff at both the import and usage sites:

-from .search import urlpatterns as search_patters
-from .webhook import urlpatterns as webhook_patters
+from .search import urlpatterns as search_patterns
+from .webhook import urlpatterns as webhook_patterns

 ...
     *issue_type_patterns,
-    *search_patters,
-    *webhook_patters
+    *search_patterns,
+    *webhook_patterns

Also applies to: 20-22

apiserver/plane/api/serializers/issue_type.py (2)

1-1: Remove unused import

The serializers module from rest_framework is imported but not directly used in the code. You should remove unused imports to keep the codebase clean.

-from rest_framework import serializers
🧰 Tools
🪛 Ruff (0.8.2)

1-1: rest_framework.serializers imported but unused

Remove unused import: rest_framework.serializers

(F401)


26-44: Check for potential inconsistency in create method

The create method adds the issue_type_id from context, but this field is also in the read_only_fields list. While this approach works, it might be clearer to handle this similarly to how workspace_id is handled in the IssueTypeSerializer (via validate method).

Consider refactoring to use the validate method approach for consistency:

 class IssueTypeCustomPropertySerializer(BaseSerializer):
     class Meta:
         model = IssueTypeCustomProperty
         fields = "__all__"
         read_only_fields = [
             "id",
             "issue_type",
             "created_at",
             "updated_at",
             "created_by",
             "updated_by",
             "deleted_at"
         ]
        
+    def validate(self, data):
+        data['issue_type_id'] = self.context["issue_type_id"]
+        return data
-    def create(self, validated_data):
-        return IssueTypeCustomProperty.objects.create(
-            **validated_data,
-            issue_type_id=self.context["issue_type_id"]
-        )
apiserver/plane/settings/storage.py (1)

91-91: Remove unnecessary blank lines

There are unnecessary blank lines added at lines 91 and 100 that don't serve any functional purpose.

try:
-            
            # Generate a presigned URL for the S3 object
            response = self.s3_client.generate_presigned_post(
                Bucket=self.aws_storage_bucket_name,
                Key=object_name,
                Fields=fields,
                Conditions=conditions,
                ExpiresIn=expiration,
            )
-            

Also applies to: 100-100

web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx (1)

267-267: Remove commented code

There's a commented implementation of the handleUpdate prop. Remove unnecessary commented code to keep the codebase clean.

-              // handleUpdate={(val) => handleFiltersUpdate("custom_properties", null, val)}
apiserver/plane/middleware/api_log_middleware.py (2)

22-32: Remove or implement commented code

This commented-out method doesn't serve any purpose as is. Either implement it or remove it completely to avoid confusion.

-    # def process_view(self, request, view_func, view_args, view_kwargs):
-    #     path_split  = request.path.split('/')
-    #     print(len(path_split))
-    #     if len(path_split) <= 6:
-    #         return request.path
-    #     if request.path.split('/')[6] == 'DEFAULT':
-    #         path_parts = request.path.split('/')
-    #         view_kwargs['project_id'] = '9f54ba83-aa85-43ce-9ce6-b2968f066e85'
-    #         
-        
-        return request.path

33-44: Clean up or implement project_rewiter method

The project_rewiter method contains commented-out code and currently just returns the original path without any modifications. Either implement the intended functionality or simplify the method.

def project_rewiter(self, request):
-    # Modify `kwargs` as needed
-    # path_split  = request.path.split('/')
-    # print(len(path_split))
-    # if len(path_split) <= 6:
-    #     return request.path
-    # if request.path.split('/')[6] == 'DEFAULT':
-    #     path_parts = request.path.split('/')
-    #     path_parts[6] = 'dab178af-a6bb-4bfb-a0a8-ae8fd702b587'
-    #     return '/'.join(path_parts)
-    
    return request.path
-    
-    
apiserver/plane/api/urls/issue_type.py (1)

10-18: Consider using distinct URL names for different routes.

Both URL patterns on lines 10-13 and 14-18 use the same name "issue-type", which could cause conflicts when using Django's URL reversing functions like reverse() or the {% url %} template tag. This may lead to unpredictable behavior when generating URLs in your application.

Consider using more specific names like "issue-type-list" for the first pattern and "issue-type-detail" for the second pattern.

 path(
     "workspaces/<str:slug>/issue-type/",
     IssueTypeAPIEndpoint.as_view(),
-    name="issue-type",
+    name="issue-type-list",
 ),
 path(
     "workspaces/<str:slug>/issue-type/<uuid:pk>/",
     IssueTypeAPIEndpoint.as_view(),
-    name="issue-type",
+    name="issue-type-detail",
 ),
apiserver/plane/db/migrations/0086_issuetypecustomproperty_delete_projectcustomproperty_and_more.py (1)

27-27: Consider more consistent related_name.

The related_name "custom_propery_issue_type" contains a typo ("propery" instead of "property"). Additionally, it would be more consistent to use the same pattern as other related_names in the model.

-                ('issue_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='custom_propery_issue_type', to='db.issuetype')),
+                ('issue_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='custom_property_issue_type', to='db.issuetype')),
docker-compose-local.yml (1)

198-198: Remove unused volume.

The rabbitmq_data volume is still defined but no service is using it after the removal of the plane-mq service. Consider removing this unused volume definition to keep the docker-compose file clean.

 volumes:
   redisdata:
   uploads:
   pgdata:
-  rabbitmq_data:
apiserver/plane/api/middleware/api_authentication.py (1)

54-56: Remove debug code and fix typo in method name.

The method rewite_project_id_in_url has a typo (should be "rewrite") and contains a commented-out debugging statement. Remove the debugging code and fix the method name for production code.

-    def rewite_project_id_in_url(self):
+    def rewrite_project_id_in_url(self):
       pass
-       # import pdb;pdb.set_trace()
apiserver/plane/settings/common.py (1)

33-35: Consider using a more specific .env filename.

The current code loads from "file.env" which is an unusual name. Consider using a more standard name like ".env" or something more descriptive that indicates the environment (e.g., "local.env", "development.env").

-print(f"BASE_DIR: {BASE_DIR}")
-load_dotenv(os.path.join(BASE_DIR, "file.env"))
+load_dotenv(os.path.join(BASE_DIR, ".env"))
apiserver/plane/api/views/__init__.py (1)

37-42: Unused imports detected.

Static analysis indicates that many of the imports in this file are unused. If these are intended for re-export, consider adding them to an __all__ list or creating a more explicit re-export pattern.

+__all__ = [
+    "ProjectAPIEndpoint",
+    "ProjectArchiveUnarchiveAPIEndpoint",
+    "StateAPIEndpoint",
+    "WorkspaceIssueAPIEndpoint",
+    "IssueAPIEndpoint",
+    "LabelAPIEndpoint",
+    "IssueLinkAPIEndpoint",
+    "IssueCommentAPIEndpoint",
+    "IssueActivityAPIEndpoint",
+    "IssueAttachmentEndpoint",
+    "IssueCustomPropertyUpdateAPIView",
+    "IssueTypeAPIEndpoint",
+    "IssueTypeCustomPropertyAPIEndpoint",
+    "IssueAttachmentV2Endpoint",
+    "CycleAPIEndpoint",
+    "CycleIssueAPIEndpoint",
+    "TransferCycleIssueAPIEndpoint",
+    "CycleArchiveUnarchiveAPIEndpoint",
+    "ModuleAPIEndpoint",
+    "ModuleIssueAPIEndpoint",
+    "ModuleArchiveUnarchiveAPIEndpoint",
+    "ProjectMemberAPIEndpoint",
+    "InboxIssueAPIEndpoint",
+    "GlobalSearchEndpoint",
+    "WebhookEndpoint",
+    "WebhookLogsEndpoint",
+    "WebhookSecretRegenerateEndpoint",
+]
🧰 Tools
🪛 Ruff (0.8.2)

37-37: .search.GlobalSearchEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


40-40: .webhook.WebhookEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


40-40: .webhook.WebhookLogsEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


41-41: .webhook.WebhookSecretRegenerateEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

web/core/components/issues/issue-detail/issue-activity/activity/actions/custom-properties.tsx (3)

14-29: Consider adding type safety for property values.

The values newValue and oldValue are directly displayed in the UI without type validation. They should be properly typed and potentially formatted based on the type of custom property (date, number, string, etc.).

-  const newValue = activity.new_value;
-  const oldValue = activity.old_value;
+  const newValue = activity.new_value !== null ? String(activity.new_value) : '';
+  const oldValue = activity.old_value !== null ? String(activity.old_value) : '';

36-42: Remove unnecessary Fragment wrapper.

The Fragment wrapper (<>...</>) on line 36 is unnecessary since it only contains one child element.

-      <>
        {isNewProperty ? (
          <>Added a Custom Property <span className="font-medium text-custom-text-100">{customPropertyKey}</span> with value <span className="font-medium text-custom-text-100">{newValue}</span>.</>
        ) : (
          <>Updated the value of <span className="font-medium text-custom-text-100">{customPropertyKey}</span> from <span className="font-medium text-custom-text-100">{oldValue}</span> to <span className="font-medium text-custom-text-100">{newValue}</span>.</>
        )}
-      </>
🧰 Tools
🪛 Biome (1.9.4)

[error] 36-42: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)


30-45: Implement accessibility improvements for the component.

The component could be improved with screen reader accessibility by using semantic elements or ARIA roles.

  return (
    <IssueActivityBlockComponent
      icon={<DoubleCircleIcon className="h-4 w-4 flex-shrink-0 text-custom-text-200" />}
      activityId={activityId}
      ends={ends}
    >
-      <>
        {isNewProperty ? (
-          <>Added a Custom Property <span className="font-medium text-custom-text-100">{customPropertyKey}</span> with value <span className="font-medium text-custom-text-100">{newValue}</span>.</>
+          <p aria-label={`Added custom property ${customPropertyKey} with value ${newValue}`}>
+            Added a Custom Property <span className="font-medium text-custom-text-100">{customPropertyKey}</span> with value <span className="font-medium text-custom-text-100">{newValue}</span>.
+          </p>
        ) : (
-          <>Updated the value of <span className="font-medium text-custom-text-100">{customPropertyKey}</span> from <span className="font-medium text-custom-text-100">{oldValue}</span> to <span className="font-medium text-custom-text-100">{newValue}</span>.</>
+          <p aria-label={`Updated custom property ${customPropertyKey} from ${oldValue} to ${newValue}`}>
+            Updated the value of <span className="font-medium text-custom-text-100">{customPropertyKey}</span> from <span className="font-medium text-custom-text-100">{oldValue}</span> to <span className="font-medium text-custom-text-100">{newValue}</span>.
+          </p>
        )}
-      </>
    </IssueActivityBlockComponent>
  );
🧰 Tools
🪛 Biome (1.9.4)

[error] 36-42: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

apiserver/plane/app/permissions/project.py (3)

49-49: Avoid raw print statements in production code.

Consider using a logger (e.g., Python’s built-in logging module) instead of a print statement for better control and log management.


53-54: Consistent superuser bypass.

This check repeats the same superuser bypass logic. If you rely on the same pattern in multiple places, consider factoring it into a common base permission method to reduce duplication.


159-161: Repeated superuser bypass check.

These lines mirror the same pattern above. As previously noted, consider standardizing or verifying consistency across all permission classes.

apiserver/plane/api/views/issue_type.py (3)

1-26: Remove unused imports.

Static analysis indicates that several imports like Case, CharField, Exists, F, Func, Max, OuterRef, Q, Value, When, Subquery, MultiPartParser, FormParser, and issue_activity (line 35) are unused. Removing them will keep the codebase clean and reduce confusion.

- from django.db.models import (
-     Case,
-     CharField,
-     Exists,
-     F,
-     Func,
-     Max,
-     OuterRef,
-     Q,
-     Value,
-     When,
-     Subquery,
- )
- from rest_framework.parsers import MultiPartParser, FormParser
- from plane.bgtasks.issue_activities_task import issue_activity
🧰 Tools
🪛 Ruff (0.8.2)

8-8: django.db.models.Case imported but unused

Remove unused import

(F401)


9-9: django.db.models.CharField imported but unused

Remove unused import

(F401)


10-10: django.db.models.Exists imported but unused

Remove unused import

(F401)


11-11: django.db.models.F imported but unused

Remove unused import

(F401)


12-12: django.db.models.Func imported but unused

Remove unused import

(F401)


13-13: django.db.models.Max imported but unused

Remove unused import

(F401)


14-14: django.db.models.OuterRef imported but unused

Remove unused import

(F401)


15-15: django.db.models.Q imported but unused

Remove unused import

(F401)


16-16: django.db.models.Value imported but unused

Remove unused import

(F401)


17-17: django.db.models.When imported but unused

Remove unused import

(F401)


18-18: django.db.models.Subquery imported but unused

Remove unused import

(F401)


25-25: rest_framework.parsers.MultiPartParser imported but unused

Remove unused import

(F401)


25-25: rest_framework.parsers.FormParser imported but unused

Remove unused import

(F401)


43-86: Check the IssueTypeAPIEndpoint.get logic for performance.

This method retrieves either a specific record or paginated results. Make sure you have appropriate indexing (e.g., on workspace__slug) to optimize lookups for large data sets.


198-240: Validate use of Workspace object in IssueTypeCustomPropertyAPIEndpoint.

You assign workspace (line 200) but never use it. Also, watch out for the ValidationError reference at line 236 if django.core.exceptions.ValidationError is not already imported or spelled differently. Ensure you’re referencing the right object or remove unused variables.

🧰 Tools
🪛 Ruff (0.8.2)

200-200: Local variable workspace is assigned to but never used

Remove assignment to unused variable workspace

(F841)


236-236: Undefined name ValidationError

(F821)

apiserver/plane/api/views/base.py (4)

78-78: Use logging library instead of print.

Printing exceptions is generally not recommended for production. Consider using structured logging with error levels.


89-89: Avoid multiple statements on one line.

Static analysis flags the semicolon usage. For clarity and maintainability, split the import and traceback calls onto separate lines, or remove the semicolon:

- import traceback; traceback.print_exc()
+ import traceback
+ traceback.print_exc()
🧰 Tools
🪛 Ruff (0.8.2)

89-89: Multiple statements on one line (semicolon)

(E702)


129-144: Ensure check_kwargs usage does not introduce hidden dependencies.

This method calls MagicSignInEndpoint to mutate data if slug is present. If that’s intended, confirm no duplication with your normal authentication flow, and handle any failures or partial updates.


145-164: Review user creation logic in get_or_create_user_from_headers.

This approach automatically creates a user if X-Assume-Role is set and the user does not exist. Ensure you handle use cases around security, default password assignment, or user duplication properly.

apiserver/plane/app/views/view/base.py (2)

3-3: Remove unused import.

The import Count from django.db.models is not used anywhere in this file.

-from django.db.models import Count
🧰 Tools
🪛 Ruff (0.8.2)

3-3: django.db.models.Count imported but unused

Remove unused import: django.db.models.Count

(F401)


314-328: Consider optimizing property grouping.

The property grouping implementation could be optimized. You're retrieving all properties, serializing them, then looping through them to build a grouped dictionary.

Consider using Django's annotation/aggregation features to group properties at the database level.

def listCustomProperty(self, request, slug):
    customPropertyAllowedKeys = ALLOWED_CUSTOM_PROPERTY_WORKSPACE_MAP.get(slug, [])
-   custom_properties = IssueCustomProperty.objects.filter(key__in=customPropertyAllowedKeys)
-   serializer = IssueCustomPropertySerializer(custom_properties, many=True)
-
-   groupedCustomProperties = {}
-   for item in serializer.data:
-       key = item.get("key")
-       value = item.get("value")
-       if value is None or key not in customPropertyAllowedKeys:
-           continue
-       groupedCustomProperties.setdefault(key, set()).add(value)
-
-   groupedUniqueCustomProperties = {key: list(values) for key, values in groupedCustomProperties.items()}
+   # Group at database level to reduce memory usage
+   from django.db.models import Func, F, Value
+   from django.contrib.postgres.aggregates import ArrayAgg
+   
+   grouped_properties = (
+       IssueCustomProperty.objects
+       .filter(key__in=customPropertyAllowedKeys, value__isnull=False)
+       .values('key')
+       .annotate(values=ArrayAgg('value', distinct=True))
+   )
+   
+   groupedUniqueCustomProperties = {item['key']: item['values'] for item in grouped_properties}
    return Response(groupedUniqueCustomProperties, status=status.HTTP_200_OK)
web/core/services/workspace.service.ts (1)

292-300: Use more specific types instead of 'any'.

The field parameter is typed as any, which reduces TypeScript's ability to provide type checking. Consider using a more specific type.

- async getIssueAdditionalProperties(workspaceSlug: string, projectId: string , field: any): Promise<any> {
+ async getIssueAdditionalProperties(workspaceSlug: string, projectId: string , field: string): Promise<Record<string, unknown>> {
apiserver/plane/authentication/provider/credentials/magic_code.py (1)

131-133: Remove debug print statements.

These debugging print statements should be removed before merging to production.

- keys = ri.keys('*')
- print("All keys in redis:", keys)
- print("Key to be checked:", self.key)
apiserver/plane/api/urls/issue.py (1)

80-89: Inconsistent URL structure for custom properties endpoints

The newly added custom properties endpoints follow a different URL structure than the other issue-related endpoints. While most endpoints include projects/<str:project_id>, these new ones skip the project level and go directly from workspace to issue.

This inconsistency might cause confusion for API users and could make future maintenance more difficult.

Consider aligning the URL structure with existing patterns:

- path(
-     'workspaces/<str:slug>/issues/<uuid:issue_id>/custom-properties/<uuid:pk>/',
-     IssueCustomPropertyUpdateAPIView.as_view(),
-     name="update-issue-custom-property",
- ),
-     path(
-     'workspaces/<str:slug>/issues/<uuid:issue_id>/custom-properties/',
-     IssueCustomPropertyUpdateAPIView.as_view(),
-     name="create-issue-custom-property",
- ),
+ path(
+     'workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/custom-properties/<uuid:pk>/',
+     IssueCustomPropertyUpdateAPIView.as_view(),
+     name="update-issue-custom-property",
+ ),
+ path(
+     'workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/custom-properties/',
+     IssueCustomPropertyUpdateAPIView.as_view(),
+     name="create-issue-custom-property",
+ ),
apiserver/plane/api/views/project.py (1)

242-242: Extra blank line

There's an extra blank line at line 242 which can be removed for consistency.

web/core/constants/issue.ts (2)

113-124: Potential typo in variable name

The variable whileListedCustomProperties appears to have a typo. Did you mean whiteListedCustomProperties?

-const whileListedCustomProperties = [
+const whiteListedCustomProperties = [
  { key: "trip_reference_number", title: "Trip Reference Number" },
  { key: "reference_number", title: "Reference Number" },
  ...
];

535-549: Duplicated property definitions

The ISSUE_ADDITIONAL_PROPERTIES array contains largely the same properties as whileListedCustomProperties defined earlier in the file. This duplication could lead to maintenance issues if they need to be updated separately.

Consider reusing the existing definitions instead of duplicating them:

-export const ISSUE_ADDITIONAL_PROPERTIES: {
-    key: keyof TIssue;
-    title: string;
-  }[] = [
-    { key: "trip_reference_number", title: "Trip Ref Number" },
-    { key: "reference_number", title: "Reference Number" },
-    { key: "hub_code", title: "Hub Code" },
-    { key: "hub_name", title: "Hub Name" },
-    { key: "customer_code", title: "Customer Code" },
-    { key: "customer_name", title: "Customer Name" },
-    { key: "vendor_code", title: "Vendor Code" },
-    { key: "vendor_name", title: "Vendor Name" },
-    { key: "worker_code", title: "Worker Code" },
-    { key: "worker_name", title: "Worker Name" }
-  ];
+export const ISSUE_ADDITIONAL_PROPERTIES: {
+    key: keyof TIssue;
+    title: string;
+  }[] = whiteListedCustomProperties.map(prop => ({
+    key: prop.key,
+    title: prop.key === "trip_reference_number" ? "Trip Ref Number" : prop.title
+  }));

Note: If you need to maintain different titles or properties, consider creating a base set of properties that both arrays can reference and extend.

packages/types/src/issues/issue.d.ts (1)

72-72: Consider the implications of using an index signature.

Adding [key: string]: any allows for any property to be added to TIssue objects. While this provides flexibility, it also reduces type safety and could lead to runtime errors if properties are accessed incorrectly.

If you only need the specific new properties, consider removing this index signature and explicitly defining all needed properties instead.

apiserver/plane/api/views/member.py (3)

125-135: Profile setup could benefit from error handling.

While the profile setup code looks good functionally, consider adding error handling for the profile creation and update operations to ensure robustness.

 if not user:
     user = self.create_user(user_data)
-    profile, _ = Profile.objects.get_or_create(user=user)
-    profile.last_workspace_id = workspace.id
-    profile.onboarding_step.update({
-        'profile_complete': True,
-        'workspace_join': True
-    })
-    profile.is_tour_completed = True
-    profile.is_onboarded = True
-    profile.company_name = workspace.name
-    profile.save()
+    try:
+        profile, _ = Profile.objects.get_or_create(user=user)
+        profile.last_workspace_id = workspace.id
+        profile.onboarding_step.update({
+            'profile_complete': True,
+            'workspace_join': True
+        })
+        profile.is_tour_completed = True
+        profile.is_onboarded = True
+        profile.company_name = workspace.name
+        profile.save()
+    except Exception as e:
+        # Log the error but continue execution
+        print(f"Error setting up user profile: {e}")

165-172: Redundant save call in workspace member creation.

The create_workspace_member method has a redundant save() call since WorkspaceMember.objects.create() already saves the object.

def create_workspace_member(self, workspace_id, user, role=15):
    workspace_member = WorkspaceMember.objects.create(
        workspace_id=workspace_id,
        member=user,
        role=role
    )
-    workspace_member.save()

173-180: Redundant save call in project member creation.

The create_project_member method has a redundant save() call since ProjectMember.objects.create() already saves the object.

def create_project_member(self, project_id, user, role=15):
    # Create a project member for the user if not already a member
    project_member = ProjectMember.objects.create(
        project_id=project_id,
        member=user,
        role=role
    )
-    project_member.save()
apiserver/Dockerfile.api (1)

67-77: Comprehensive CMD instruction for different environment types.

The CMD instruction now handles different environment types effectively, allowing for different behavior based on the deployment scenario. However, there's a small typo in the Flower URL prefix parameter.

elif [ "${ENV_TYPE}" = "celery-beat" ]; then \
-    (celery -A plane flower --port=5555 --address=0.0.0.0 --url-prefix=flower &) && celery -A plane beat -l info; \
+    (celery -A plane flower --port=5555 --address=0.0.0.0 --url_prefix=flower &) && celery -A plane beat -l info; \

Note that in the "celery" environment type, you're using --url_prefix but in the "celery-beat" environment, you're using --url-prefix. They should be consistent.

web/core/components/issues/issue-layouts/filters/header/filters/additional-properties.tsx (2)

27-39: API fetch with potential improvements.

The API fetch logic could be improved with a loading state, better error handling, and prevention of unnecessary API calls when the component unmounts.

const [options, setOptions] = useState<{ label: string; value: string }[]>([]);
const [previewEnabled, setPreviewEnabled] = useState(true);
const [visibleOptions, setVisibleOptions] = useState(5);
+ const [isLoading, setIsLoading] = useState(false);
+ const [error, setError] = useState<string | null>(null);

useEffect(() => {
  const fetchOptions = async () => {
+   if (!workspaceSlug || !projectId || !additionalPropertyKey) return;
+   
+   setIsLoading(true);
+   setError(null);
    try {
      const response = await workspaceService.getIssueAdditionalProperties(workspaceSlug.toString(), projectId.toString(), props.additionalPropertyKey);
      const formattedOptions = response.data.map((item: string) => ({ label: item, value: item })) || [];
      setOptions(formattedOptions);
    } catch (error) {
      console.error(`Error fetching ${additionalPropertyKey} options:`, error);
+     setError(`Failed to load ${additionalPropertyTitle || additionalPropertyKey} options`);
+   } finally {
+     setIsLoading(false);
    }
  };

+  let isMounted = true;
+  if (isMounted) {
    fetchOptions();
+  }
+  
+  return () => {
+    isMounted = false;
+  };
}, [workspaceSlug, projectId, additionalPropertyKey]);

45-79: Render loading and error states in the component.

The component should display loading and error states to improve user experience.

return (
  <>
    <FilterHeader
      title={`${additionalPropertyTitle} ${appliedFilters?.length ? `(${appliedFilters.length})` : ""}`}
      isPreviewEnabled={previewEnabled}
      handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
    />
    {previewEnabled && (
      <div>
+       {isLoading && (
+         <p className="text-xs text-custom-text-400">Loading...</p>
+       )}
+       {error && (
+         <p className="text-xs text-red-500">{error}</p>
+       )}
-       {filteredOptions.length > 0 ? (
+       {!isLoading && !error && filteredOptions.length > 0 ? (
          <>
            {filteredOptions.slice(0, visibleOptions).map(({ label, value }) => (
              <FilterOption
                key={value}
                isChecked={appliedFilters?.includes(value) ?? false}
                onClick={() => handleUpdate(value)}
                title={label}
              />
            ))}
            {filteredOptions.length > 5 && (
              <button
                className="text-blue-500 text-xs mt-2"
                onClick={() => setVisibleOptions(visibleOptions === 5 ? filteredOptions.length : 5)}
              >
                {visibleOptions === 5 ? "View More" : "View Less"}
              </button>
            )}
          </>
-       ) : (
+       ) : (!isLoading && !error) ? (
          <p className="text-xs italic text-custom-text-400">No Matches Found</p>
+       ) : (
+         null
        )}
      </div>
    )}
  </>
);
web/core/constants/spreadsheet.ts (1)

181-270: Extensive duplication in property definitions.

The new property definitions contain significant duplication that could be reduced with a more programmatic approach. Consider using a factory function to create these property objects.

+ // Define a factory function for creating standard property objects
+ const createStandardProperty = (
+   key: string,
+   title: string
+ ) => ({
+   title,
+   ascendingOrderKey: key,
+   ascendingOrderTitle: "A",
+   descendingOrderKey: `-${key}`,
+   descendingOrderTitle: "Z",
+   icon: Tags,
+   Column: SpreadsheetStandardPropertyColumn,
+ });
+
+ // Create property objects using the factory function
+ const standardProperties = {
+   trip_reference_number: createStandardProperty("trip_reference_number", "Trip Ref Number"),
+   reference_number: createStandardProperty("reference_number", "Reference Number"),
+   hub_code: createStandardProperty("hub_code", "Hub Code"),
+   hub_name: createStandardProperty("hub_name", "Hub Name"),
+   customer_code: createStandardProperty("customer_code", "Customer Code"),
+   customer_name: createStandardProperty("customer_name", "Customer Name"),
+   vendor_name: createStandardProperty("vendor_name", "Vendor Name"),
+   vendor_code: createStandardProperty("vendor_code", "Vendor Code"),
+   worker_code: createStandardProperty("worker_code", "Worker Code"),
+   worker_name: createStandardProperty("worker_name", "Worker Name"),
+ };
+
+ // Merge the standard properties with the existing SPREADSHEET_PROPERTY_DETAILS
+ export const SPREADSHEET_PROPERTY_DETAILS = {
+   // Existing properties...
+   ...standardProperties,
+ };

This approach would significantly reduce code duplication while maintaining the same functionality.

web/core/components/issues/peek-overview/properties.tsx (1)

346-357: Refine type usage for prop.

Using any dilutes type safety. Define a proper interface or type to ensure clarity and maintainability.

- {ISSUE_ADDITIONAL_PROPERTIES.map((prop: any) =>
+ {ISSUE_ADDITIONAL_PROPERTIES.map((prop: { key: keyof TIssue; title: string }) =>
web/core/components/issues/issue-layouts/filters/header/filters/custom-properties.tsx (1)

119-125: Simplify the ternary expression for isChecked.

You can directly pass the boolean evaluation without explicitly using ? true : false.

- isChecked={appliedFilters?.includes(`${groupKey}:${property}`) ? true : false}
+ isChecked={appliedFilters?.includes(`${groupKey}:${property}`)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 121-121: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

apiserver/plane/utils/issue_filters.py (3)

6-6: Remove unused import.

Q is imported but not used in the final code.

- from django.db.models import Q
🧰 Tools
🪛 Ruff (0.8.2)

6-6: django.db.models.Q imported but unused

Remove unused import: django.db.models.Q

(F401)


271-271: Remove or replace debug print.

Leaving debug statements in production code can clutter logs.

- print(created_bys)
+ # print(created_bys)  # Remove or replace with logging if necessary

590-590: Remove or replace debug print in filter_custom_properties.

Helps maintain a cleaner log output.

- print(issue_filter)
+ # print(issue_filter)  // or use a logger if required
apiserver/plane/app/views/issue/base.py (3)

60-60: Remove unused import.

ALLOWED_CUSTOM_PROPERTY_WORKSPACE_MAP is never used.

- from plane.utils.constants import ALLOWED_CUSTOM_PROPERTY_WORKSPACE_MAP
🧰 Tools
🪛 Ruff (0.8.2)

60-60: plane.utils.constants.ALLOWED_CUSTOM_PROPERTY_WORKSPACE_MAP imported but unused

Remove unused import: plane.utils.constants.ALLOWED_CUSTOM_PROPERTY_WORKSPACE_MAP

(F401)


72-74: Remove unused permission imports.

These are not referenced in the file.

-    ProjectEntityPermission,
-    ProjectLitePermission,
-    ProjectMemberPermission,
🧰 Tools
🪛 Ruff (0.8.2)

72-72: plane.app.permissions.ProjectEntityPermission imported but unused

Remove unused import

(F401)


73-73: plane.app.permissions.ProjectLitePermission imported but unused

Remove unused import

(F401)


74-74: plane.app.permissions.ProjectMemberPermission imported but unused

Remove unused import

(F401)


438-438: Eliminate or guard debug print statements.

Multiple print statements in production code can cause noise in logs.

- print(serializer.data)
- print(issue)
- print(serializer.data)
+ # print(serializer.data)
+ # print(issue)
+ # ...

Also applies to: 503-503, 670-670

web/core/components/issues/custom-properties.tsx (2)

58-70: Consider aligning the naming convention between server response and local properties.

The code uses customProp.name from the server response and maps it to key in the local object, while also using local objects keyed by prop.key. This can be confusing when debugging. Unifying the naming (e.g., renaming name to key server-side or vice versa) could improve clarity and reduce confusion around property matching.


80-99: Double-check error handling for updateCustomProperties calls.

Currently, when a custom property update fails, the error is logged to the console, but there's no user-facing feedback to indicate that the update was not saved. Consider adding in-component or global error notifications or retry logic to inform users of failures and allow them to address issues more gracefully.

apiserver/plane/api/serializers/issue.py (2)

36-41: Remove the unused uuid_obj assignment to address the static analysis warning.

The variable uuid_obj is assigned in is_uuid but never read. Simplify by removing this unused assignment:

-def is_uuid(value):
-    try:
-        uuid_obj = uuid.UUID(str(value))  # Convert to string in case it's not already
-        return True
-    except (ValueError, TypeError):
-        return False
+def is_uuid(value):
+    try:
+        uuid.UUID(str(value))  # Convert to string in case it's not already
+        return True
+    except (ValueError, TypeError):
+        return False
🧰 Tools
🪛 Ruff (0.8.2)

38-38: Local variable uuid_obj is assigned to but never used

Remove assignment to unused variable uuid_obj

(F841)


160-176: Avoid printing sensitive data in production logs.

There's a print(data) statement that might expose confidential information. Silence or log it securely at an appropriate logging level if needed.

apiserver/plane/db/models/issue.py (1)

146-155: Consider indexing frequently searched fields.

You've introduced several new fields (hub_code, vendor_code, customer_code, etc.). If you anticipate queries filtering by these fields, adding database indexes will improve query performance.

apiserver/plane/bgtasks/issue_activities_task.py (4)

370-379: Enhance error handling for fallback logic in track_assignees.

The newly introduced fallback logic that checks both "assignee_ids" and "assignees" is a good approach. However, consider improving error handling in case these fields contain invalid data or reference non-existent user IDs. You may also remove the extra blank line at line 372 to maintain consistency.


602-603: Fix inconsistent spacing and unify condition checks.

Line 602 lacks a space before is: requested_data.get("assignees")is not None. Also, consider simplifying the conditional logic to handle emptiness:

-if requested_data.get("assignee_ids") is not None or requested_data.get("assignees")is not None:
+if requested_data.get("assignee_ids") or requested_data.get("assignees"):

Also applies to: 612-613


1613-1644: Consider robust JSON parsing and error handling.

In update_custom_property_activity, you convert string inputs to JSON without a try-except block. If either current_instance or requested_data is malformed, it can raise a JSONDecodeError. Consider adding error handling or validating JSON before parsing to avoid runtime issues.


1646-1676: Add protective fallback for custom property creation.

In create_custom_property_activity, it's good to see a default 'unknown_key'. However, consider validating the key/value pair more thoroughly to avoid inconsistent or invalid data. Even a quick check or logging would help identify malformed requests more quickly.

apiserver/plane/api/views/webhook.py (1)

18-39: Monitor the usage of 410_GONE.

While checking for duplications is correct, returning HTTP_410_GONE when the URL already exists is uncommon—409_CONFLICT is more typical for duplicate resource conflicts.

apiserver/plane/api/views/search.py (3)

37-48: Optionally include workspace_member__is_active check.

Filtering workspaces by workspace_member__member=self.request.user is good, but consider verifying that the membership is active to avoid pulling in inactive or deleted memberships.


68-106: Regex-based sequence ID matching may raise performance concerns.

Using re.findall(r"\b\d+\b", query) is flexible but can be expensive for large queries. Consider bounding your search or optimizing this logic for better performance.


132-156: Check for module-level archiving.

While you exclude archived projects, confirm whether Module also needs an archived_at check for consistency if such a field exists.

demo.Jenkinsfile (1)

33-35: Use versioned Docker images for a robust deployment strategy.

Instead of tagging images with latest, consider employing semantic versioning or commit-based tags to ensure reproducible builds, ease rollbacks, and maintain better traceability.

-def webImageName = "plane-frontend:latest"
-def adminImageName = "plane-adminpanel:latest"
-def apiImageName = "plane-apiserver:latest"
+def webImageName = "plane-frontend:${BUILD_TAG}"
+def adminImageName = "plane-adminpanel:${BUILD_TAG}"
+def apiImageName = "plane-apiserver:${BUILD_TAG}"
apiserver/plane/api/views/issue.py (3)

37-37: Remove unused import.

IssueTypeSerializer is imported but not used anywhere. Removing it avoids confusion and meets linting standards.

-    IssueTypeSerializer,
🧰 Tools
🪛 Ruff (0.8.2)

37-37: plane.api.serializers.IssueTypeSerializer imported but unused

Remove unused import: plane.api.serializers.IssueTypeSerializer

(F401)


57-57: Remove unused import.

IssueType is imported from plane.db.models but is never referenced. Removing it keeps the code clean.

-    IssueType,
🧰 Tools
🪛 Ruff (0.8.2)

57-57: plane.db.models.IssueType imported but unused

Remove unused import: plane.db.models.IssueType

(F401)


156-156: Avoid leaving debug print statements.

print(query) might clutter logs in production. Consider replacing it with structured logging or removing it.

-print(query)
+# logger.debug("Issue query: %s", query)
apiserver/plane/authentication/views/app/magic.py (1)

287-287: Remove unused variable.

is_app is assigned at line 287 but never used afterward. Remove it to maintain code clarity and pass lint checks.

-        is_app = request.POST.get("is_app", False)
🧰 Tools
🪛 Ruff (0.8.2)

287-287: Local variable is_app is assigned to but never used

Remove assignment to unused variable is_app

(F841)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2d1b3fb and 40a01e9.

📒 Files selected for processing (107)
  • admin/Dockerfile.admin (1 hunks)
  • admin/ce/components/common/upgrade-button.tsx (1 hunks)
  • admin/core/components/admin-sidebar/help-section.tsx (0 hunks)
  • aio/nginx.conf (1 hunks)
  • apiserver/Dockerfile.api (2 hunks)
  • apiserver/plane/api/middleware/api_authentication.py (3 hunks)
  • apiserver/plane/api/serializers/__init__.py (1 hunks)
  • apiserver/plane/api/serializers/issue.py (11 hunks)
  • apiserver/plane/api/serializers/issue_type.py (1 hunks)
  • apiserver/plane/api/serializers/project.py (2 hunks)
  • apiserver/plane/api/serializers/webhook.py (1 hunks)
  • apiserver/plane/api/urls/__init__.py (2 hunks)
  • apiserver/plane/api/urls/issue.py (2 hunks)
  • apiserver/plane/api/urls/issue_type.py (1 hunks)
  • apiserver/plane/api/urls/project.py (2 hunks)
  • apiserver/plane/api/urls/search.py (1 hunks)
  • apiserver/plane/api/urls/state.py (1 hunks)
  • apiserver/plane/api/urls/webhook.py (1 hunks)
  • apiserver/plane/api/views/__init__.py (3 hunks)
  • apiserver/plane/api/views/attachment.py (1 hunks)
  • apiserver/plane/api/views/base.py (6 hunks)
  • apiserver/plane/api/views/issue.py (12 hunks)
  • apiserver/plane/api/views/issue_type.py (1 hunks)
  • apiserver/plane/api/views/member.py (4 hunks)
  • apiserver/plane/api/views/project.py (3 hunks)
  • apiserver/plane/api/views/search.py (1 hunks)
  • apiserver/plane/api/views/state.py (1 hunks)
  • apiserver/plane/api/views/webhook.py (1 hunks)
  • apiserver/plane/app/permissions/__init__.py (1 hunks)
  • apiserver/plane/app/permissions/project.py (7 hunks)
  • apiserver/plane/app/serializers/issue.py (5 hunks)
  • apiserver/plane/app/urls/issue.py (2 hunks)
  • apiserver/plane/app/urls/views.py (1 hunks)
  • apiserver/plane/app/views/__init__.py (1 hunks)
  • apiserver/plane/app/views/base.py (1 hunks)
  • apiserver/plane/app/views/issue/base.py (14 hunks)
  • apiserver/plane/app/views/view/base.py (6 hunks)
  • apiserver/plane/authentication/adapter/base.py (2 hunks)
  • apiserver/plane/authentication/provider/credentials/magic_code.py (3 hunks)
  • apiserver/plane/authentication/utils/redirection_path.py (1 hunks)
  • apiserver/plane/authentication/views/app/magic.py (5 hunks)
  • apiserver/plane/bgtasks/issue_activities_task.py (6 hunks)
  • apiserver/plane/bgtasks/webhook_task.py (1 hunks)
  • apiserver/plane/db/migrations/0084_projectcustomproperty_issuecustomproperty_and_more.py (1 hunks)
  • apiserver/plane/db/migrations/0085_remove_issuecustomproperty_project_custom_property_and_more.py (1 hunks)
  • apiserver/plane/db/migrations/0086_issuetypecustomproperty_delete_projectcustomproperty_and_more.py (1 hunks)
  • apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (1 hunks)
  • apiserver/plane/db/migrations/0088_alter_issuecustomproperty_issue_type.py (1 hunks)
  • apiserver/plane/db/migrations/0089_rename_issue_type_issuecustomproperty_issue_type_custom_proerty.py (1 hunks)
  • apiserver/plane/db/migrations/0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py (1 hunks)
  • apiserver/plane/db/migrations/0091_issue_customer_code_issue_hub_code_and_more.py (1 hunks)
  • apiserver/plane/db/models/__init__.py (3 hunks)
  • apiserver/plane/db/models/base.py (1 hunks)
  • apiserver/plane/db/models/issue.py (4 hunks)
  • apiserver/plane/db/models/issue_type.py (1 hunks)
  • apiserver/plane/middleware/api_log_middleware.py (2 hunks)
  • apiserver/plane/settings/common.py (7 hunks)
  • apiserver/plane/settings/redis.py (1 hunks)
  • apiserver/plane/settings/storage.py (4 hunks)
  • apiserver/plane/utils/constants.py (1 hunks)
  • apiserver/plane/utils/grouper.py (1 hunks)
  • apiserver/plane/utils/issue_filters.py (6 hunks)
  • apiserver/requirements/base.txt (3 hunks)
  • apiserver/supervisord.conf (1 hunks)
  • apiserver/templates/emails/exports/analytics.html (1 hunks)
  • demo.Jenkinsfile (1 hunks)
  • deploy/selfhost/install.sh (1 hunks)
  • docker-compose-local.yml (3 hunks)
  • docker-compose.yml (1 hunks)
  • nginx/nginx.conf.dev (1 hunks)
  • nginx/nginx.conf.template (1 hunks)
  • packages/types/src/issues/issue.d.ts (1 hunks)
  • packages/types/src/view-props.d.ts (2 hunks)
  • space/core/components/issues/filters/selection.tsx (1 hunks)
  • space/next.config.js (1 hunks)
  • web/Dockerfile.web (1 hunks)
  • web/app/[workspaceSlug]/(projects)/header.tsx (1 hunks)
  • web/app/provider.tsx (3 hunks)
  • web/app/workspace-invitations/page.tsx (1 hunks)
  • web/ce/constants/project/settings/features.tsx (1 hunks)
  • web/core/components/issues/custom-properties.tsx (1 hunks)
  • web/core/components/issues/index.ts (1 hunks)
  • web/core/components/issues/issue-detail/issue-activity/activity/actions/custom-properties.tsx (1 hunks)
  • web/core/components/issues/issue-detail/issue-activity/activity/actions/index.ts (1 hunks)
  • web/core/components/issues/issue-detail/issue-activity/activity/activity-list.tsx (2 hunks)
  • web/core/components/issues/issue-detail/sidebar.tsx (6 hunks)
  • web/core/components/issues/issue-layouts/filters/applied-filters/additional-properties.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/filters/applied-filters/filters-list.tsx (3 hunks)
  • web/core/components/issues/issue-layouts/filters/applied-filters/index.ts (1 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/additional-properties.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/custom-properties.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx (2 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/index.ts (1 hunks)
  • web/core/components/issues/issue-layouts/spreadsheet/columns/index.ts (1 hunks)
  • web/core/components/issues/issue-layouts/spreadsheet/columns/standard-property-column.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/spreadsheet/issue-column.tsx (1 hunks)
  • web/core/components/issues/peek-overview/properties.tsx (6 hunks)
  • web/core/components/workspace/sidebar/dropdown.tsx (1 hunks)
  • web/core/components/workspace/sidebar/help-section.tsx (1 hunks)
  • web/core/components/workspace/sidebar/projects-list-item.tsx (0 hunks)
  • web/core/constants/analytics.ts (1 hunks)
  • web/core/constants/dashboard.ts (1 hunks)
  • web/core/constants/issue.ts (8 hunks)
  • web/core/constants/spreadsheet.ts (4 hunks)
  • web/core/hooks/use-group-dragndrop.ts (1 hunks)
  • web/core/services/workspace.service.ts (1 hunks)
  • web/core/store/issue/helpers/issue-filter-helper.store.ts (3 hunks)
⛔ Files not processed due to max files limit (3)
  • web/core/store/issue/issue-details/issue.store.ts
  • web/helpers/issue.helper.ts
  • web/next.config.js
💤 Files with no reviewable changes (2)
  • admin/core/components/admin-sidebar/help-section.tsx
  • web/core/components/workspace/sidebar/projects-list-item.tsx
🧰 Additional context used
🧬 Code Definitions (42)
apiserver/plane/app/permissions/__init__.py (1)
apiserver/plane/app/permissions/project.py (1)
  • ProjectEntityGuestPermission (119-152)
apiserver/plane/db/migrations/0089_rename_issue_type_issuecustomproperty_issue_type_custom_proerty.py (4)
apiserver/plane/db/migrations/0085_remove_issuecustomproperty_project_custom_property_and_more.py (1)
  • Migration (6-22)
apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (1)
  • Migration (7-24)
apiserver/plane/db/migrations/0088_alter_issuecustomproperty_issue_type.py (1)
  • Migration (7-19)
apiserver/plane/db/migrations/0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py (1)
  • Migration (6-18)
apiserver/plane/app/views/__init__.py (1)
apiserver/plane/app/views/issue/base.py (2)
  • SearchAPIEndpoint (1222-1263)
  • SearchSingleValueAPI (1265-1300)
web/core/components/issues/issue-layouts/filters/applied-filters/filters-list.tsx (1)
web/core/components/issues/issue-layouts/filters/applied-filters/additional-properties.tsx (1)
  • AppliedAdditionalPropertiesFilters (14-33)
web/core/components/issues/issue-detail/issue-activity/activity/activity-list.tsx (1)
web/core/components/issues/issue-detail/issue-activity/activity/actions/custom-properties.tsx (1)
  • IssueCustomPropertyActivity (14-45)
apiserver/plane/authentication/adapter/base.py (2)
apiserver/plane/api/views/issue.py (8)
  • get (102-125)
  • get (168-313)
  • get (663-681)
  • get (744-768)
  • get (891-909)
  • get (1055-1086)
  • get (1161-1166)
  • get (1210-1221)
apiserver/plane/api/views/member.py (1)
  • get (37-58)
apiserver/plane/api/urls/search.py (1)
apiserver/plane/api/views/search.py (1)
  • GlobalSearchEndpoint (29-274)
apiserver/plane/api/serializers/project.py (1)
apiserver/plane/api/serializers/issue_type.py (1)
  • IssueTypeSerializer (7-24)
apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (3)
apiserver/plane/db/migrations/0088_alter_issuecustomproperty_issue_type.py (1)
  • Migration (7-19)
apiserver/plane/db/migrations/0089_rename_issue_type_issuecustomproperty_issue_type_custom_proerty.py (1)
  • Migration (6-18)
apiserver/plane/db/migrations/0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py (1)
  • Migration (6-18)
apiserver/plane/app/urls/views.py (1)
apiserver/plane/app/views/view/base.py (1)
  • WorkspaceViewIssuesViewSet (208-467)
apiserver/plane/db/migrations/0085_remove_issuecustomproperty_project_custom_property_and_more.py (5)
apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (1)
  • Migration (7-24)
apiserver/plane/db/migrations/0088_alter_issuecustomproperty_issue_type.py (1)
  • Migration (7-19)
apiserver/plane/db/migrations/0086_issuetypecustomproperty_delete_projectcustomproperty_and_more.py (1)
  • Migration (9-48)
apiserver/plane/db/migrations/0089_rename_issue_type_issuecustomproperty_issue_type_custom_proerty.py (1)
  • Migration (6-18)
apiserver/plane/db/migrations/0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py (1)
  • Migration (6-18)
apiserver/plane/api/serializers/__init__.py (3)
apiserver/plane/api/serializers/issue.py (1)
  • IssueCustomPropertySerializer (43-54)
apiserver/plane/app/views/issue/base.py (1)
  • IssueCustomPropertySerializer (77-88)
apiserver/plane/api/serializers/issue_type.py (2)
  • IssueTypeSerializer (7-24)
  • IssueTypeCustomPropertySerializer (26-44)
web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx (4)
web/core/constants/issue.ts (1)
  • ISSUE_ADDITIONAL_PROPERTIES (535-549)
web/core/components/issues/issue-layouts/filters/header/filters/additional-properties.tsx (1)
  • FilterAdditionalProperties (18-80)
packages/types/src/view-props.d.ts (1)
  • IIssueFilterOptions (94-116)
web/core/components/issues/issue-layouts/filters/header/filters/custom-properties.tsx (1)
  • FilterCustomProperty (19-142)
apiserver/plane/db/migrations/0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py (3)
apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (1)
  • Migration (7-24)
apiserver/plane/db/migrations/0088_alter_issuecustomproperty_issue_type.py (1)
  • Migration (7-19)
apiserver/plane/db/migrations/0089_rename_issue_type_issuecustomproperty_issue_type_custom_proerty.py (1)
  • Migration (6-18)
apiserver/plane/api/middleware/api_authentication.py (2)
apiserver/plane/api/views/issue.py (8)
  • get (102-125)
  • get (168-313)
  • get (663-681)
  • get (744-768)
  • get (891-909)
  • get (1055-1086)
  • get (1161-1166)
  • get (1210-1221)
apiserver/plane/api/views/project.py (1)
  • get (202-240)
apiserver/plane/app/urls/issue.py (1)
apiserver/plane/app/views/issue/base.py (2)
  • SearchAPIEndpoint (1222-1263)
  • SearchSingleValueAPI (1265-1300)
apiserver/plane/app/permissions/project.py (3)
apiserver/plane/api/views/base.py (2)
  • project_id (199-208)
  • workspace_slug (195-196)
apiserver/plane/db/models/project.py (1)
  • ProjectMember (215-259)
apiserver/plane/api/views/issue.py (1)
  • project__identifier (78-79)
apiserver/plane/api/views/issue_type.py (3)
apiserver/plane/api/serializers/issue_type.py (2)
  • IssueTypeSerializer (7-24)
  • IssueTypeCustomPropertySerializer (26-44)
apiserver/plane/app/permissions/project.py (1)
  • ProjectLitePermission (155-168)
apiserver/plane/db/models/issue_type.py (2)
  • IssueType (10-32)
  • IssueTypeCustomProperty (62-84)
apiserver/plane/app/views/view/base.py (3)
apiserver/plane/db/models/issue.py (1)
  • IssueCustomProperty (734-755)
apiserver/plane/utils/issue_filters.py (1)
  • issue_filters (622-661)
apiserver/plane/app/views/base.py (2)
  • fields (148-154)
  • fields (253-259)
apiserver/plane/authentication/provider/credentials/magic_code.py (1)
apiserver/plane/authentication/adapter/base.py (1)
  • set_user_data (44-45)
apiserver/plane/db/migrations/0086_issuetypecustomproperty_delete_projectcustomproperty_and_more.py (5)
apiserver/plane/db/migrations/0085_remove_issuecustomproperty_project_custom_property_and_more.py (1)
  • Migration (6-22)
apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (1)
  • Migration (7-24)
apiserver/plane/db/migrations/0088_alter_issuecustomproperty_issue_type.py (1)
  • Migration (7-19)
apiserver/plane/db/migrations/0089_rename_issue_type_issuecustomproperty_issue_type_custom_proerty.py (1)
  • Migration (6-18)
apiserver/plane/db/migrations/0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py (1)
  • Migration (6-18)
apiserver/plane/db/models/__init__.py (2)
apiserver/plane/db/models/issue.py (1)
  • IssueCustomProperty (734-755)
apiserver/plane/db/models/issue_type.py (2)
  • IssueType (10-32)
  • IssueTypeCustomProperty (62-84)
apiserver/plane/api/views/__init__.py (5)
apiserver/plane/api/views/project.py (2)
  • ProjectAPIEndpoint (124-377)
  • ProjectArchiveUnarchiveAPIEndpoint (380-400)
apiserver/plane/api/views/issue_type.py (1)
  • IssueTypeAPIEndpoint (43-196)
apiserver/plane/api/views/attachment.py (1)
  • IssueAttachmentV2Endpoint (18-174)
apiserver/plane/api/views/search.py (1)
  • GlobalSearchEndpoint (29-274)
apiserver/plane/api/views/webhook.py (3)
  • WebhookEndpoint (16-107)
  • WebhookLogsEndpoint (121-129)
  • WebhookSecretRegenerateEndpoint (110-118)
apiserver/plane/api/views/project.py (1)
apiserver/plane/api/serializers/project.py (1)
  • create (66-88)
web/core/constants/issue.ts (1)
packages/types/src/issues/issue.d.ts (1)
  • TIssue (52-73)
web/core/components/issues/issue-layouts/filters/header/filters/additional-properties.tsx (1)
web/core/services/workspace.service.ts (1)
  • WorkspaceService (20-301)
web/core/constants/spreadsheet.ts (1)
web/core/components/issues/issue-layouts/spreadsheet/columns/standard-property-column.tsx (1)
  • SpreadsheetStandardPropertyColumn (12-22)
apiserver/plane/api/urls/state.py (1)
apiserver/plane/api/views/state.py (1)
  • StateAPIEndpoint (16-162)
apiserver/plane/api/urls/issue_type.py (1)
apiserver/plane/api/views/issue_type.py (2)
  • IssueTypeAPIEndpoint (43-196)
  • IssueTypeCustomPropertyAPIEndpoint (198-240)
web/core/components/issues/issue-detail/sidebar.tsx (2)
web/core/components/issues/custom-properties.tsx (2)
  • CustomProperty (5-10)
  • CustomProperties (20-192)
web/core/constants/issue.ts (1)
  • ISSUE_ADDITIONAL_PROPERTIES (535-549)
apiserver/plane/app/views/issue/base.py (2)
apiserver/plane/app/permissions/project.py (3)
  • ProjectEntityPermission (83-116)
  • ProjectLitePermission (155-168)
  • ProjectMemberPermission (47-80)
apiserver/plane/api/serializers/issue.py (1)
  • IssueCustomPropertySerializer (43-54)
web/core/components/issues/peek-overview/properties.tsx (2)
web/core/components/issues/custom-properties.tsx (2)
  • CustomProperty (5-10)
  • CustomProperties (20-192)
web/core/constants/issue.ts (1)
  • ISSUE_ADDITIONAL_PROPERTIES (535-549)
apiserver/plane/api/views/search.py (2)
apiserver/plane/api/views/base.py (3)
  • fields (211-217)
  • BaseAPIView (40-226)
  • project_id (199-208)
apiserver/plane/db/models/issue.py (1)
  • Issue (112-276)
apiserver/plane/app/serializers/issue.py (3)
apiserver/plane/db/models/issue.py (17)
  • IssueCustomProperty (734-755)
  • Meta (198-202)
  • Meta (287-291)
  • Meta (319-331)
  • Meta (347-359)
  • Meta (375-387)
  • Meta (401-405)
  • Meta (435-439)
  • Meta (485-489)
  • Meta (530-534)
  • Meta (553-565)
  • Meta (580-584)
  • Meta (600-604)
  • Meta (617-629)
  • Meta (646-658)
  • Meta (677-689)
  • Meta (712-728)
apiserver/plane/app/views/issue/base.py (1)
  • IssueCustomPropertySerializer (77-88)
apiserver/plane/api/serializers/issue.py (1)
  • IssueCustomPropertySerializer (43-54)
apiserver/plane/api/views/webhook.py (2)
apiserver/plane/app/views/base.py (3)
  • BaseAPIView (166-268)
  • fields (148-154)
  • fields (253-259)
apiserver/plane/api/serializers/webhook.py (2)
  • WebhookSerializer (15-128)
  • WebhookLogSerializer (131-135)
apiserver/plane/api/views/attachment.py (3)
apiserver/plane/api/serializers/issue.py (3)
  • IssueAttachmentSerializer (445-457)
  • create (181-268)
  • create (419-427)
apiserver/plane/settings/storage.py (3)
  • S3Storage (14-166)
  • generate_presigned_post (66-106)
  • generate_presigned_url (116-144)
apiserver/plane/db/models/base.py (1)
  • save (25-42)
apiserver/plane/api/views/base.py (4)
apiserver/plane/db/models/project.py (1)
  • Project (53-176)
apiserver/plane/authentication/views/app/magic.py (2)
  • MagicSignInEndpoint (88-272)
  • add_user_to_workspace (95-101)
apiserver/plane/api/views/search.py (1)
  • get (236-274)
apiserver/plane/api/views/member.py (1)
  • get (37-58)
apiserver/plane/api/views/issue.py (1)
apiserver/plane/api/serializers/issue.py (4)
  • IssueCustomPropertySerializer (43-54)
  • IssueSerializer (56-359)
  • create (181-268)
  • create (419-427)
apiserver/plane/api/serializers/issue.py (3)
apiserver/plane/db/models/issue.py (17)
  • IssueCustomProperty (734-755)
  • Meta (198-202)
  • Meta (287-291)
  • Meta (319-331)
  • Meta (347-359)
  • Meta (375-387)
  • Meta (401-405)
  • Meta (435-439)
  • Meta (485-489)
  • Meta (530-534)
  • Meta (553-565)
  • Meta (580-584)
  • Meta (600-604)
  • Meta (617-629)
  • Meta (646-658)
  • Meta (677-689)
  • Meta (712-728)
apiserver/plane/api/views/member.py (4)
  • ProjectMemberAPIEndpoint (31-180)
  • create_user (150-164)
  • create_workspace_member (165-171)
  • create_project_member (173-180)
apiserver/plane/api/serializers/issue_type.py (1)
  • create (40-44)
web/core/components/issues/issue-layouts/filters/header/filters/custom-properties.tsx (1)
web/core/services/workspace.service.ts (1)
  • WorkspaceService (20-301)
apiserver/plane/api/urls/issue.py (3)
apiserver/plane/api/views/attachment.py (1)
  • IssueAttachmentV2Endpoint (18-174)
apiserver/plane/api/views/issue_type.py (1)
  • IssueTypeAPIEndpoint (43-196)
apiserver/plane/api/views/issue.py (2)
  • IssueCustomPropertyUpdateAPIView (1168-1277)
  • IssueAPIEndpoint (127-582)
apiserver/plane/authentication/views/app/magic.py (3)
apiserver/plane/api/serializers/project.py (2)
  • ProjectSerializer (15-88)
  • create (66-88)
apiserver/plane/api/views/base.py (1)
  • BaseAPIView (40-226)
apiserver/plane/api/views/project.py (1)
  • create_project (34-122)
🪛 Ruff (0.8.2)
apiserver/plane/app/permissions/__init__.py

14-14: .project.ProjectEntityGuestPermission imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/app/views/__init__.py

135-135: .issue.base.SearchAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


136-136: .issue.base.SearchSingleValueAPI imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/api/serializers/project.py

12-12: .issue_type.IssueTypeSerializer imported but unused

Remove unused import: .issue_type.IssueTypeSerializer

(F401)

apiserver/plane/api/serializers/__init__.py

13-13: .issue.IssueCustomPropertySerializer imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


15-15: .issue_type.IssueTypeSerializer imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


15-15: .issue_type.IssueTypeCustomPropertySerializer imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/api/serializers/issue_type.py

1-1: rest_framework.serializers imported but unused

Remove unused import: rest_framework.serializers

(F401)

apiserver/plane/bgtasks/webhook_task.py

407-407: Local variable event_data is assigned to but never used

Remove assignment to unused variable event_data

(F841)


408-408: Local variable actor_data is assigned to but never used

Remove assignment to unused variable actor_data

(F841)

apiserver/plane/api/views/issue_type.py

8-8: django.db.models.Case imported but unused

Remove unused import

(F401)


9-9: django.db.models.CharField imported but unused

Remove unused import

(F401)


10-10: django.db.models.Exists imported but unused

Remove unused import

(F401)


11-11: django.db.models.F imported but unused

Remove unused import

(F401)


12-12: django.db.models.Func imported but unused

Remove unused import

(F401)


13-13: django.db.models.Max imported but unused

Remove unused import

(F401)


14-14: django.db.models.OuterRef imported but unused

Remove unused import

(F401)


15-15: django.db.models.Q imported but unused

Remove unused import

(F401)


16-16: django.db.models.Value imported but unused

Remove unused import

(F401)


17-17: django.db.models.When imported but unused

Remove unused import

(F401)


18-18: django.db.models.Subquery imported but unused

Remove unused import

(F401)


25-25: rest_framework.parsers.MultiPartParser imported but unused

Remove unused import

(F401)


25-25: rest_framework.parsers.FormParser imported but unused

Remove unused import

(F401)


35-35: plane.bgtasks.issue_activities_task.issue_activity imported but unused

Remove unused import: plane.bgtasks.issue_activities_task.issue_activity

(F401)


140-140: Local variable requested_data is assigned to but never used

Remove assignment to unused variable requested_data

(F841)


141-141: Local variable current_instance is assigned to but never used

Remove assignment to unused variable current_instance

(F841)


142-142: Undefined name issue_comment

(F821)


162-162: Undefined name issue_comment

(F821)


200-200: Local variable workspace is assigned to but never used

Remove assignment to unused variable workspace

(F841)


236-236: Undefined name ValidationError

(F821)

apiserver/plane/app/views/view/base.py

3-3: django.db.models.Count imported but unused

Remove unused import: django.db.models.Count

(F401)

apiserver/plane/db/models/__init__.py

44-44: .issue.IssueCustomProperty imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


71-71: .project.ProjectPublicMember imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


115-115: .issue_type.IssueType imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


115-115: .issue_type.IssueTypeCustomProperty imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/api/views/__init__.py

2-2: .project.ProjectAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


3-3: .project.ProjectArchiveUnarchiveAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


16-16: .issue.IssueCustomPropertyUpdateAPIView imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


18-18: .issue_type.IssueTypeAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


18-18: .issue_type.IssueTypeCustomPropertyAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


19-19: .attachment.IssueAttachmentV2Endpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


37-37: .search.GlobalSearchEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


40-40: .webhook.WebhookEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


40-40: .webhook.WebhookLogsEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


41-41: .webhook.WebhookSecretRegenerateEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/api/views/project.py

253-253: Undefined name user

(F821)

apiserver/plane/app/views/issue/base.py

60-60: plane.utils.constants.ALLOWED_CUSTOM_PROPERTY_WORKSPACE_MAP imported but unused

Remove unused import: plane.utils.constants.ALLOWED_CUSTOM_PROPERTY_WORKSPACE_MAP

(F401)


72-72: plane.app.permissions.ProjectEntityPermission imported but unused

Remove unused import

(F401)


73-73: plane.app.permissions.ProjectLitePermission imported but unused

Remove unused import

(F401)


74-74: plane.app.permissions.ProjectMemberPermission imported but unused

Remove unused import

(F401)

apiserver/plane/utils/issue_filters.py

6-6: django.db.models.Q imported but unused

Remove unused import: django.db.models.Q

(F401)

apiserver/plane/api/views/attachment.py

9-9: plane.app.permissions.allow_permission imported but unused

Remove unused import: plane.app.permissions.allow_permission

(F401)

apiserver/plane/api/views/base.py

89-89: Multiple statements on one line (semicolon)

(E702)

apiserver/plane/api/views/issue.py

37-37: plane.api.serializers.IssueTypeSerializer imported but unused

Remove unused import: plane.api.serializers.IssueTypeSerializer

(F401)


57-57: plane.db.models.IssueType imported but unused

Remove unused import: plane.db.models.IssueType

(F401)

apiserver/plane/api/serializers/issue.py

38-38: Local variable uuid_obj is assigned to but never used

Remove assignment to unused variable uuid_obj

(F841)

apiserver/plane/api/urls/issue.py

10-10: plane.api.views.IssueTypeAPIEndpoint imported but unused

Remove unused import: plane.api.views.IssueTypeAPIEndpoint

(F401)

apiserver/plane/authentication/views/app/magic.py

287-287: Local variable is_app is assigned to but never used

Remove assignment to unused variable is_app

(F841)

🪛 Biome (1.9.4)
web/core/components/issues/issue-detail/issue-activity/activity/activity-list.tsx

[error] 47-47: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx

[error] 249-249: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

web/core/components/issues/issue-detail/issue-activity/activity/actions/custom-properties.tsx

[error] 36-42: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

web/core/components/issues/issue-layouts/filters/header/filters/custom-properties.tsx

[error] 121-121: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

🔇 Additional comments (134)
web/app/provider.tsx (1)

43-51: Good implementation of the sign-out handler.

The async function with proper error handling using toast notifications provides a good user experience.

apiserver/templates/emails/exports/analytics.html (1)

1-7: LGTM: Improved HTML formatting and standards compliance.

The changes to this HTML email template improve readability through multi-line formatting and update the <br/> tags to the XHTML-compliant <br /> format. These changes enhance maintainability without altering the email's content or functionality.

web/Dockerfile.web (1)

105-107: Container configuration properly implemented

The addition of the EXPOSE 3000 directive correctly documents the container's network port, while the CMD node web/server.js web instruction defines the proper startup command. These are standard Docker practices that complete the container configuration.

apiserver/plane/api/urls/project.py (1)

15-16: Ensure proper ID validation in view implementation

Changing from uuid:pk to str:pk removes automatic UUID format validation at the URL dispatcher level. While this provides more flexibility, ensure that proper validation of project IDs is implemented in the ProjectAPIEndpoint view to prevent invalid IDs from causing issues.

apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (1)

19-23: Appropriate field modification for flexibility

Making the value field nullable and allowing blank values provides more flexibility for custom properties, which is a good change.

web/core/components/workspace/sidebar/dropdown.tsx (1)

108-108:

Details

❓ Verification inconclusive

Verify disabled dropdown button intention

Adding disabled={true} makes the dropdown button non-interactive. This is a significant UX change that prevents users from accessing workspace selection functionality.

Is this change intentional? If it's meant to be a temporary fix for a TypeScript error (as suggested by the PR title), consider addressing the underlying type issue instead of disabling the entire component functionality.


🏁 Script executed:

#!/bin/bash
# Check if there are any TypeScript errors related to this component
rg -B 3 -A 3 "SidebarDropdown" --glob "*.log" --glob "*.error"

# Look for related property type errors in TypeScript config or error logs
rg "property" --glob "*.log" --glob "*.error" | grep -i "type\|typescript\|ts"

Length of output: 439


Action Required: Confirm Intention for the Disabled Dropdown Button

The dropdown button is permanently disabled with disabled={true}, which removes access to the workspace selection functionality. Our initial automated search for related TypeScript errors did not return any results—though this may be due to filtering issues with the log search. Please verify whether this change is an intentional design decision or a temporary workaround for a TypeScript issue. If it is temporary, consider addressing the underlying type problem rather than disabling the component entirely.

apiserver/plane/api/urls/state.py (1)

7-7:

Details

❓ Verification inconclusive

Ensure consistent project_id handling across codebase

Changing <uuid:project_id> to <str:project_id> in URL patterns makes the API more flexible in accepting project identifiers, but requires verification that all related code handles string IDs properly.

This change may require updates to database queries and validation logic. Make sure the StateAPIEndpoint view and related code can handle string project IDs correctly:

I'm particularly concerned about potential inconsistencies if other related endpoints still expect UUID project IDs.

Also applies to: 12-12


🏁 Script executed:

#!/bin/bash
# Check for uses of project_id in the StateAPIEndpoint class
rg -A 3 "project_id" "apiserver/plane/api/views/state.py"

# Check for other URL patterns that might need similar updates for consistency
rg "<uuid:project_id>" --glob="*.py" --glob="!*/migrations/*" 

Length of output: 17449


Action Required: Verify Consistency in Project ID Handling Across Endpoints

The URL change in apiserver/plane/api/urls/state.py—switching from <uuid:project_id> to <str:project_id>—appears to work fine in the StateAPIEndpoint as the view simply retrieves the project ID from kwargs and uses it directly in queries and serializer contexts. However, our repository-wide search shows that several other endpoints (e.g., in files like apiserver/plane/api/urls/inbox.py and apiserver/plane/app/urls/state.py) still use <uuid:project_id>. This discrepancy raises two points for review:

  • Validation & Conversion: Confirm that the database model and related business logic can correctly work with a string value for project_id. If the underlying field is a UUID, ensure that either:

    • The string is converted/validated appropriately, or
    • The design intentionally permits non-UUID values.
  • Endpoint Consistency: If a uniform handling of project_id is desired across the API, decide whether to update the other URL patterns to <str:project_id> or to add conversion logic in the StateAPIEndpoint (and possibly in other views) to maintain consistency.

Please revisit these areas to verify that the change does not introduce subtle bugs or inconsistency issues with other endpoints.

aio/nginx.conf (1)

6-8:

Details

❓ Verification inconclusive

Consider reconciling duplicate client_max_body_size settings.

You have explicitly set client_max_body_size 50M; on line 8 while also referencing ${FILE_SIZE_LIMIT} on line 15. Verify whether you intend to override the environment variable value or if this duplication is unintentional, as it can lead to confusion or inconsistent behavior.


🏁 Script executed:

#!/bin/bash
# Description: Check for references to client_max_body_size and FILE_SIZE_LIMIT in aio/nginx.conf to confirm if you're intentionally overriding the environment variable.

rg 'client_max_body_size|FILE_SIZE_LIMIT' aio/nginx.conf -A 2

Length of output: 223


Action: Reconcile Duplicate client_max_body_size Settings

It appears that the configuration file sets client_max_body_size twice in different contexts:

  • A fixed value of 50M is set (around line 8).
  • Later, within the server block, an environment variable is used: ${FILE_SIZE_LIMIT}.

This duplication may be unintentional or could lead to unpredictable behavior. Please verify if the fixed value is meant to override the variable or if both declarations should be consolidated for consistency.

nginx/nginx.conf.template (1)

6-8:

Details

❓ Verification inconclusive

Double-check configuration consistency.

These added directives align with the changes in aio/nginx.conf. However, as with aio/nginx.conf, confirm whether you intend to override the environment variable-based client_max_body_size (line 15) with a hard-coded 50M limit.


🏁 Script executed:

#!/bin/bash
# Description: Verify references to client_max_body_size and FILE_SIZE_LIMIT in nginx.conf.template for consistency.

rg 'client_max_body_size|FILE_SIZE_LIMIT' nginx/nginx.conf.template -A 2

Length of output: 234


Nginx Configuration Consistency Check

  • In nginx/nginx.conf.template, there is a global directive setting client_max_body_size 50M; while within the server { … } block it uses client_max_body_size ${FILE_SIZE_LIMIT};.
  • Please confirm if the intention is to override the environment variable-based setting with the hard-coded 50M value, as done in aio/nginx.conf, or if the two settings should be unified.
web/core/constants/dashboard.ts (1)

261-268: The Projects menu item is commented out.

This change removes the "Projects" option from the sidebar menu. Make sure this is intentional and won't affect user navigation within the application.

Is this temporary or part of a redesign to simplify the sidebar? Consider adding a comment explaining why these menu items are commented out rather than completely removed if this is a temporary change.

apiserver/plane/app/serializers/issue.py (4)

667-678: New serializer added for custom properties.

Added IssueCustomPropertySerializer to handle custom properties for issues.

This serializer properly defines the fields and read-only properties for the IssueCustomProperty model, which will help in handling custom property data in API responses.


740-741: Added type_id field to IssueSerializer.

Added type_id to the fields of the IssueSerializer.

This field is necessary for properly identifying issue types, which appears to be related to the custom properties functionality being implemented.


759-760: Added custom_properties field to IssueDetailSerializer.

Incorporated the custom properties serializer into the IssueDetailSerializer and added it to the fields list.

This change properly integrates custom properties with issue details, allowing them to be included in API responses when fetching issue details.

Also applies to: 765-766


711-721:

Details

❓ Verification inconclusive

Added multiple reference fields to issue serializer.

Added fields like trip_reference_number, hub_code, customer_name, etc. to the IssueSerializer.

These appear to be domain-specific reference fields. Ensure that these fields are properly defined in the Issue model. Additionally, consider grouping these reference fields into a nested structure if they logically belong together.


🏁 Script executed:

#!/bin/bash
# Verify that these fields exist in the Issue model
grep -A 30 "class Issue" apiserver/plane/db/models/issue.py | grep -E "trip_reference_number|reference_number|hub_code|hub_name|customer_code|customer_name|vendor_name|vendor_code|worker_code|worker_name"

Length of output: 206


Action: Verify model field definitions and consider grouping related reference fields

The added reference fields (trip_reference_number, reference_number, hub_code, hub_name, customer_code, customer_name, vendor_name, vendor_code, worker_code, worker_name) need to be confirmed as being defined in the Issue model (apiserver/plane/db/models/issue.py). The initial grep command did not produce any output, so please manually verify (or re-run an extensive search) to ensure these fields are present. Additionally, if these reference-related fields represent a cohesive domain group, consider refactoring them into a nested structure for better organization.

web/core/components/issues/index.ts (1)

15-15: Added export for custom properties module.

Added a new export statement for the custom properties components.

This change correctly exports the custom properties components, making them available to be imported by other parts of the application. This is consistent with the overall approach of exporting all components through index files.

web/core/components/issues/issue-layouts/filters/header/filters/index.ts (1)

14-14: Clean addition of new export for additional properties filtering

This export follows the established pattern in the file and makes the components from the additional-properties module available to importers of this index file, enhancing the filtering capabilities with custom properties.

web/core/components/issues/issue-layouts/spreadsheet/columns/index.ts (1)

15-15: Export addition looks good

This new export follows the consistent pattern in the file and makes the standard-property-column components available through this index. This change supports the handling of custom properties in the issue management system.

web/core/components/issues/issue-layouts/filters/applied-filters/index.ts (1)

12-12: Export properly implemented for applied filters

This addition correctly follows the established pattern and makes the AppliedAdditionalPropertiesFilters component available to importers. This enhances the filtering capabilities in the UI for custom properties.

web/core/components/issues/issue-detail/issue-activity/activity/actions/index.ts (1)

20-20: LGTM! Export for custom properties activity actions

This export correctly exposes the custom properties module in the activity actions index. This enables proper tracking and display of custom property changes in the issue activity feed.

apiserver/plane/app/permissions/__init__.py (1)

14-14:

Details

✅ Verification successful

New permission import needs to be verified

The ProjectEntityGuestPermission has been added to the imports. This permission class extends access control to accommodate guest users for project-related functionalities, but the static analysis indicates it might be unused within this context.


🏁 Script executed:

#!/bin/bash
# Check if ProjectEntityGuestPermission is used in the codebase

echo "Searching for references to ProjectEntityGuestPermission:"
rg "ProjectEntityGuestPermission" --type py -A 2 -B 2

Length of output: 1537


Verified usage of ProjectEntityGuestPermission in issue views

The new permission import is confirmed to be used in the codebase—in particular, it's referenced in the Issue view within apiserver/plane/api/views/issue.py (both where it is explicitly mentioned and in the permission_classes attribute). This verifies that the import isn't unused, and no further changes are required.

🧰 Tools
🪛 Ruff (0.8.2)

14-14: .project.ProjectEntityGuestPermission imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/app/views/__init__.py (1)

135-136:

Details

✅ Verification successful

Verify usage of newly imported search endpoints

The SearchAPIEndpoint and SearchSingleValueAPI classes have been imported from .issue.base, but static analysis indicates they might be unused. These endpoints provide search capabilities for issue-related fields within a workspace and project.


🏁 Script executed:

#!/bin/bash
# Check if the newly imported search endpoints are used in the codebase

echo "Searching for references to SearchAPIEndpoint:"
rg "SearchAPIEndpoint" --type py -A 2 -B 2

echo "Searching for references to SearchSingleValueAPI:"
rg "SearchSingleValueAPI" --type py -A 2 -B 2

# Check for URL patterns that might utilize these endpoints
echo "Checking URL patterns that might use these endpoints:"
rg "path\(.*search.*" --type py -A 2 -B 2

Length of output: 2974


Search endpoints usage verified—imports are in use

After verifying the codebase:

  • SearchAPIEndpoint is defined in apiserver/plane/app/views/issue/base.py and referenced in apiserver/plane/app/urls/issue.py (e.g., mapped to the URL pattern for "workspaces/<str:slug>/projects/<str:project_id>/search").
  • SearchSingleValueAPI is defined in apiserver/plane/app/views/issue/base.py and similarly used in URL configurations within apiserver/plane/app/urls/issue.py.

These findings confirm that the imported endpoints in apiserver/plane/app/views/__init__.py are actively used within the project. No changes are required.

🧰 Tools
🪛 Ruff (0.8.2)

135-135: .issue.base.SearchAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


136-136: .issue.base.SearchSingleValueAPI imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/db/migrations/0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py (1)

1-18: Migration corrects spelling in field name

This migration fixes a typo in the field name, changing issue_type_custom_proerty to the correctly spelled issue_type_custom_property. This is part of a sequence of migrations that have been refining the schema of the issuecustomproperty model.

web/core/constants/analytics.ts (1)

57-57: Fixed syntax by removing trailing comma

The trailing comma has been removed from the last object in the ANALYTICS_X_AXIS_VALUES array. While trailing commas are valid in modern JavaScript/TypeScript and can make diffs cleaner when adding new items, this change likely aligns with the project's style guidelines.

admin/Dockerfile.admin (1)

86-88: Good Docker configuration

The exposed port and CMD instruction correctly define how the container should be run, following Docker best practices.

web/core/components/issues/issue-layouts/spreadsheet/issue-column.tsx (1)

46-46:

Details

❓ Verification inconclusive

Fix for property type propagation

This change correctly passes the property prop to the Column component, which is properly typed as keyof IIssueDisplayProperties. This addresses a TypeScript error where a required prop wasn't being passed down to the child component.


🏁 Script executed:

#!/bin/bash
# Check the Column component to confirm it expects a property prop
echo "Checking SPREADSHEET_PROPERTY_DETAILS to understand Column component requirements..."
rg -A 5 "SPREADSHEET_PROPERTY_DETAILS" --type tsx

Length of output: 256


Action Required: Re-run Verification Script for TSX Files

The initial script failed because ripgrep didn’t recognize the "tsx" file type. Please run the updated script below—which uses a glob pattern to properly target TSX files—to verify that the Column component (or related component) references SPREADSHEET_PROPERTY_DETAILS and that the property prop is correctly typed as keyof IIssueDisplayProperties.

#!/bin/bash
# Re-checking SPREADSHEET_PROPERTY_DETAILS in TSX files using glob pattern
echo "Re-checking SPREADSHEET_PROPERTY_DETAILS in TSX files with -g pattern..."
rg -A 5 "SPREADSHEET_PROPERTY_DETAILS" -g "*.tsx"

Once you verify that the expected output appears and confirms that the Column component requires and correctly types the property prop, you can confirm that the change (passing property={property}) resolves the TypeScript error.

web/ce/constants/project/settings/features.tsx (1)

87-88: Time tracking feature now available for all users

The changes make time tracking accessible to all users by setting isPro: false and isEnabled: true. This modification democratizes the feature, removing its premium-only restriction.

web/app/[workspaceSlug]/(projects)/header.tsx (2)

3-8: GitHub link and related imports removed from header

The commented imports suggest a deliberate removal of GitHub integration from the header component.


14-14: Event tracking constant no longer needed

The GITHUB_REDIRECTED constant has been commented out since the GitHub link in the header has been removed.

admin/ce/components/common/upgrade-button.tsx (1)

12-16: Upgrade button functionality disabled

The upgrade button has been effectively disabled by replacing it with an empty anchor element. The original implementation directing users to "plane.so/one" is preserved in comments for potential future restoration.

apiserver/plane/utils/grouper.py (1)

97-106: Custom fields added for issue results

These additions to the required_fields list enhance the issue data response with transport/logistics-specific fields like trip references, hub details, customer and vendor information. This change ensures these custom properties are properly included in query results.

apiserver/requirements/base.txt (3)

13-13: New dependency for environment variable management

Adding python-dotenv suggests the codebase now uses environment variables from .env files for configuration, which is a good practice for managing different deployment environments.


33-33: Minor version upgrade for django-storages

Upgrading django-storages from 1.14.2 to 1.14.4 is likely for bug fixes or improvements.


4-4:

Details

❓ Verification inconclusive

Verify Django downgrade is intentional

Django has been downgraded from 4.2.16 to 4.2.14. While this might be for compatibility reasons, downgrading could have security implications if the newer version contained security fixes.


🌐 Web query:

Are there any security fixes in Django 4.2.16 that are not in Django 4.2.14?

💡 Result:

Django 4.2.16 includes two security fixes not present in 4.2.14:

Security Fixes Introduced in 4.2.16

  1. CVE-2024-45230:
    Moderate-severity denial-of-service vulnerability in django.utils.html.urlize(), where processing specific character sequences in large inputs could exhaust system resources[1][4][10].

  2. CVE-2024-45231:
    Low-severity user email enumeration vulnerability via password reset failures. Attackers could infer valid user emails by observing error responses when email delivery failed[1][4][16].

Security Fixes in 4.2.14 (Not Present in 4.2.16)

Django 4.2.14 addressed four vulnerabilities resolved in earlier releases:

The 4.2.16 release only addresses the two newer CVEs listed above. For comprehensive protection, upgrading directly to 4.2.16 (or later) is required to include all cumulative security patches[1][6].

Citations:


Security Implications: Confirm Intentional Django Version Downgrade

File: apiserver/requirements/base.txt (Line 4)

The current change downgrades Django from 4.2.16 to 4.2.14. Note that Django 4.2.16 introduced two important security fixes that are missing in 4.2.14:

  • CVE-2024-45230: A moderate-severity denial-of-service vulnerability in django.utils.html.urlize().
  • CVE-2024-45231: A low-severity issue regarding user email enumeration via password reset failures.

Please verify that this downgrade is intentional and that any compatibility reasons have been weighed against the potential security implications. If the downgrade remains necessary, consider documenting the rationale and any planned mitigations.

apiserver/plane/api/serializers/__init__.py (1)

13-13: New serializers for custom properties and issue types

The addition of IssueCustomPropertySerializer, IssueTypeSerializer, and IssueTypeCustomPropertySerializer to the package exports enhances the API's capability to handle custom properties and issue types.

While static analysis flags these as unused imports, this is a common pattern in Python where __init__.py files intentionally re-export symbols to simplify imports for consumers of the package.

Also applies to: 15-15

🧰 Tools
🪛 Ruff (0.8.2)

13-13: .issue.IssueCustomPropertySerializer imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/db/migrations/0088_alter_issuecustomproperty_issue_type.py (1)

14-18: Improved relationship between issue custom properties and types

This migration properly modifies the issue_type field in the issuecustomproperty model to be an optional foreign key to issuetypecustomproperty. The on_delete=SET_NULL behavior ensures that deleting an issue type custom property won't cascade delete the issue custom property itself, which prevents data loss.

The defined related name issue_type_custom_property provides a clear reverse lookup path from issue type custom properties to their associated issue custom properties.

apiserver/plane/app/views/base.py (1)

123-124: Good debugging enhancement!

Adding detailed query logging when there are more than 20 queries will help identify potential N+1 query issues during development.

apiserver/supervisord.conf (1)

1-16: Well-structured Supervisor configuration for Celery

The configuration properly sets up:

  • Celery worker with appropriate log level
  • Flower monitoring tool on port 5555
  • Proper log file paths for both services
  • Auto-restart for reliability

This is a good approach for managing background task processing in the application.

web/core/components/issues/issue-layouts/filters/applied-filters/filters-list.tsx (3)

17-17: Good addition of the AppliedAdditionalPropertiesFilters component.

This import correctly includes the new component for handling additional property filters.


40-40: Well-defined constant for additional filter properties.

The additionalFilters constant properly defines the list of filter keys that will be handled by the additional properties filter component.


139-145: Properly implemented conditional rendering for additional properties filters.

The implementation follows the established pattern in the codebase and correctly passes the necessary props to the AppliedAdditionalPropertiesFilters component. This enhances the filtering functionality with additional property support.

apiserver/plane/app/urls/issue.py (1)

27-28: Good addition of search endpoints.

These imports correctly include the necessary view classes for the new search functionality.

apiserver/plane/authentication/adapter/base.py (2)

152-155: Fixed username handling for user creation

The code now properly checks for a username from user data before defaulting to a UUID. This enhances the authentication flow by allowing pre-defined usernames to be preserved when available.


175-175: Minor formatting improvement

Added a blank line after retrieving user details for better code readability.

web/core/components/issues/issue-layouts/filters/applied-filters/additional-properties.tsx (1)

1-33: LGTM: Well-implemented filter component for custom properties

This new component correctly handles the display and removal of additional property filters. The implementation follows React best practices with proper typing and observer pattern for reactivity.

web/core/components/issues/issue-detail/issue-activity/activity/activity-list.tsx (1)

27-27: Added import for custom property activity handling

Properly imported the IssueCustomPropertyActivity component to handle custom property changes in the activity list.

web/app/workspace-invitations/page.tsx (1)

7-7: Removed Star icon from imports

The Star icon import has been removed from lucide-react imports, aligning with the removal of the GitHub star call-to-action from the UI.

nginx/nginx.conf.dev (1)

6-8: Approved configuration for handling larger requests.

These nginx configuration directives improve handling of large request bodies and enable chunked transfer encoding.

apiserver/plane/api/serializers/issue_type.py (1)

7-24: LGTM - The IssueTypeSerializer implementation looks good

The implementation properly extends the BaseSerializer and adds the workspace_id from context during validation. The Meta class correctly defines read-only fields and exclusions.

apiserver/plane/settings/storage.py (3)

16-17: LGTM - Added standard storage class variables

The added class variables file_overwrite and location follow Django's storage backend conventions.


22-26: LGTM - Good implementation of get_available_name method

The implementation follows Django's storage pattern, returning the original name when file_overwrite is True, and using the parent class implementation otherwise.


49-49:

Details

❓ Verification inconclusive

Verify HTTPS enforcement behavior

The URL is now hardcoded to use HTTPS protocol. Make sure this change doesn't break functionality for environments where HTTP might be required.


🏁 Script executed:

#!/bin/bash
# Check if there are any environment-specific configurations that might rely on HTTP
grep -r "AWS_S3_ENDPOINT_URL.*http:" --include="*.py" --include="*.env*" .
grep -r "MINIO_ENDPOINT_URL.*http:" --include="*.py" --include="*.env*" .

Length of output: 360


Action Required: Confirm HTTPS Enforcement Impact on Env Configurations

The code now hardcodes the URL scheme to HTTPS with:

f"https://{request.get_host()}"

However, our grep output from configuration files shows that some environment examples still set endpoints (e.g., AWS_S3_ENDPOINT_URL in .env.example and variables.env) to use HTTP (http://plane-minio:9000). Please verify that using HTTPS in the code doesn’t conflict with these environments. If non-HTTPS endpoints are needed (for example, in development or local testing setups), consider making the URL scheme configurable or updating the environment documentation accordingly.

docker-compose-local.yml (3)

23-24: Port exposure for MinIO improves local development.

Exposing the MinIO console port (9090) on the host makes it easier to access the web console for managing the object storage during local development. This is a good improvement.


38-39: Port exposure for PostgreSQL enables direct database access.

Exposing the PostgreSQL port (5432) allows direct connections to the database from the host machine, which is helpful for debugging and using database management tools during local development.


115-116: Interactive terminal access for the API service is useful for debugging.

Adding stdin_open: true and tty: true to the API service enables interactive terminal sessions, which makes it easier to debug the API service using tools like docker attach or when running with docker-compose up.

apiserver/plane/api/middleware/api_authentication.py (1)

67-67: Fix method call to match the corrected method name.

Update the call to validate_api_token to ensure it passes the assume_role_value parameter correctly.

apiserver/plane/settings/common.py (4)

28-28: Good addition for environment variable loading.

Adding the dotenv library for environment variable loading improves configuration flexibility across different environments.


156-156: Approved CORS header addition.

Adding the "X-Assume-Role" header to CORS_ALLOW_HEADERS is necessary for cross-origin requests that use this header.


275-275: Verify the impact of enabling file overwriting in S3.

Changing AWS_S3_FILE_OVERWRITE to True means files in S3 can be overwritten, which could lead to data loss if not managed properly. Ensure this is the intended behavior and that there are mechanisms to handle potential conflicts.


365-368:

Details

❓ Verification inconclusive

Security concerns with cookie settings.

The security-related cookie settings have been commented out and modified. SESSION_COOKIE_SECURE should be enabled in production environments to prevent cookies from being sent over unencrypted connections.


🏁 Script executed:

#!/bin/bash
# Check if this is a production configuration file
grep -A 5 -B 5 "PRODUCTION" apiserver/plane/settings/common.py
# Check if there are different settings in production-specific settings files
find apiserver/plane/settings -name "*.py" -exec grep -l "SESSION_COOKIE_SECURE" {} \;

Length of output: 187


Action Required: Validate Production Cookie Security Settings

The production configuration (in apiserver/plane/settings/common.py) now sets SESSION_COOKIE_SECURE via the variable secure_origins instead of a hard-coded True. Since this is the only place this setting appears, please verify that in your production environment secure_origins evaluates to True, ensuring cookies are only sent over encrypted connections. If secure_origins is intended to support multiple environments dynamically, please add documentation or inline comments clarifying its expected value in production.

apiserver/plane/api/urls/webhook.py (1)

9-31: URL patterns follow RESTful conventions.

The URL patterns are well-structured and follow RESTful conventions, clearly identifying resources and actions.

apiserver/plane/api/views/__init__.py (3)

1-4: Improved code formatting for imports.

The multi-line import format improves readability.

🧰 Tools
🪛 Ruff (0.8.2)

2-2: .project.ProjectAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


3-3: .project.ProjectArchiveUnarchiveAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


16-17: Approved import for custom property update view.

The import for IssueCustomPropertyUpdateAPIView is correctly placed within the issue-related imports.

🧰 Tools
🪛 Ruff (0.8.2)

16-16: .issue.IssueCustomPropertyUpdateAPIView imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


18-19: Added imports for issue type and attachment endpoints.

The imports for IssueTypeAPIEndpoint, IssueTypeCustomPropertyAPIEndpoint, and IssueAttachmentV2Endpoint are necessary for the expanded functionality.

🧰 Tools
🪛 Ruff (0.8.2)

18-18: .issue_type.IssueTypeAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


18-18: .issue_type.IssueTypeCustomPropertyAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


19-19: .attachment.IssueAttachmentV2Endpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

web/core/components/issues/issue-detail/issue-activity/activity/actions/custom-properties.tsx (1)

1-13: Properly structured React component with TypeScript.

The component imports, type definitions, and setup follow best practices for React with TypeScript.

apiserver/plane/app/permissions/project.py (8)

18-19: Confirm superuser bypass is intentional.

These lines grant unrestricted access to superusers. If that’s expected, it’s fine. Otherwise, verify that this is the intended behavior in all scenarios.


33-33: Recheck role inclusion for project creation.

The comment above suggests only workspace owners or admins should create projects, but this line explicitly includes the Guest role. Ensure that this is desired or correct any mismatched logic or docstring.


56-56: No functional change.

A blank line was added here. This is purely cosmetic; no further action needed.


68-68: Verify role set for creating projects.

Including the Guest role here is the same scenario as on line 33. Confirm whether guests should truly be able to perform project creation or modifications.


73-73: No functional change.

Another blank line added. No action needed.


77-77: Check role-based logic for project updates.

The code comment states “Only Project Admins,” but the role__in list includes Guest and Member. Confirm that it’s correct to let guests update project attributes.


88-89: Superuser override.

Same pattern as before. Ensure there’s no risk in automatically granting all superusers total access without additional checks.


113-117: Role expansion includes Guest.

These lines allow guests to create and edit project attributes. If that matches your requirements, great. If not, revert or adjust the role set accordingly.

apiserver/plane/api/views/base.py (3)

11-11: Validate new imports.

Project and User are imported. Verify they are actually used within this module to avoid introducing unused dependencies.


115-117: Check side effects of modifying kwargs and request.user.

These calls can have significant side effects (e.g., creating workspace memberships). Confirm concurrency logic, user validation, and error handling in upstream and downstream code so they can handle unexpected modifies to kwargs and request.user.


165-176: Confirm membership logic in ensure_member_in_workspace.

This relies on MagicSignInEndpoint again, which might cause side effects (like auto-creating workspace members). Validate that this is desired for all inbound requests. If not, consider restricting it to specific endpoints.

apiserver/plane/app/views/view/base.py (2)

63-74: LGTM! Good serializer implementation.

The serializer is well-structured with appropriate field definitions and read-only fields.


331-339: Good approach to handling custom properties filtering.

Creating a copy of the filters before modifying them is a good practice. The implementation correctly separates custom properties from other filters.

web/core/services/workspace.service.ts (1)

281-290: LGTM! API method follows established patterns.

The implementation of getIssuesCustomProperties follows the standard pattern used throughout the service.

apiserver/plane/authentication/provider/credentials/magic_code.py (1)

150-150:

Details

❓ Verification inconclusive

Verify impact of changing is_password_autoset to False.

Changing is_password_autoset from True to False may affect how password resets work. Ensure this change aligns with the intended authentication flow.


🏁 Script executed:

#!/bin/bash
# Search for places where is_password_autoset is used in the codebase
rg "is_password_autoset" --type py

Length of output: 2812


Verify is_password_autoset behavior across authentication flows

After reviewing the codebase, we found that in credential-based providers (e.g., in both magic_code.py and email.py), the flag is explicitly set to False—which aligns with the user model default—while OAuth providers (e.g., in gitlab.py, google.py, github.py) deliberately set it to True. This inconsistency suggests that the different authentication flows are expected to handle password setup differently.

  • Action Points:
    • Confirm that for credential-based authentication (magic code/email), setting is_password_autoset to False is intentional and does not inadvertently impact password reset logic.
    • Double-check that the divergence from OAuth providers’ behavior (where the flag remains True) is well-documented and aligns with your overall authentication flow.
packages/types/src/view-props.d.ts (2)

83-89: Type expansion for custom properties improves filter capabilities

The addition of custom property types for logistics data (customer codes, hub codes, reference numbers, etc.) provides more granular filtering capabilities for issues, aligning with the requirements in the PR objective to fix TypeScript errors related to property types.


109-115: Consistent type definitions for filter options

The filter options interface has been properly updated to include all the new custom properties, maintaining type consistency with the TIssueParams type above. This ensures type safety when using these properties in filters.

apiserver/plane/api/urls/issue.py (2)

71-79: Updated to use new IssueAttachmentV2Endpoint

The attachment endpoint has been updated to use the V2 version of the API, which according to the related code snippets handles file uploads more effectively with presigned URLs and better error handling.


21-27:

Details

✅ Verification successful

Project ID parameter type changed from UUID to string

The parameter type for project_id has been changed from uuid to str in all URL patterns. Ensure all related views and functions that consume this parameter have been updated to handle string values rather than UUIDs.


🏁 Script executed:

#!/bin/bash
# Check if project_id is still treated as UUID in related views
rg -A 5 "def.*project_id.*" --glob="apiserver/plane/api/views/issue.py"

Length of output: 10049


Action Required: Confirm Handling of project_id as String

The shell script verification confirms that all instance methods in apiserver/plane/api/views/issue.py now accept the project_id parameter as a string. For example, calls such as:

  • project = Project.objects.get(pk=project_id)

directly use the incoming project_id value without any conversion to a UUID. Please verify that downstream logic (e.g., model field types and any implicit validations) properly supports string values as expected.

apiserver/plane/api/views/project.py (1)

34-122: Good refactoring of project creation logic

Extracting the project creation logic into a separate function improves code organization and maintainability. The function handles all the necessary steps for project creation in a cohesive way.

web/core/constants/issue.ts (2)

380-386: Added custom properties to issue list filters

The addition of custom properties to the filters array provides more flexible and powerful filtering capabilities, particularly for logistics-related data like hub codes and reference numbers.


326-332: Added custom properties to my_issues spreadsheet filters

Adding these custom property filters to the My Issues view enables consistent filtering capabilities across different views.

apiserver/plane/db/migrations/0084_projectcustomproperty_issuecustomproperty_and_more.py (1)

1-69: Migration file looks well structured.

This migration creates two new models: ProjectCustomProperty and IssueCustomProperty with appropriate fields, relationships, and constraints. The unique constraints on ProjectCustomProperty ensure data integrity by preventing duplicate entries.

packages/types/src/issues/issue.d.ts (1)

61-67: New properties align with PR objectives.

These new properties properly extend the TIssue type with custom properties and shipping-related fields, which addresses the TypeScript error mentioned in the PR objectives.

web/core/store/issue/helpers/issue-filter-helper.store.ts (3)

85-85: Filter implementation for custom properties.

The custom properties filter has been added correctly to match the pattern of the other filters.


107-112: Consistent implementation of shipping-related filters.

These additional filters for shipping-related fields are implemented correctly and follow the established pattern.


154-159: Consistent implementation in computedFilters method.

The shipping-related properties are correctly handled in the computedFilters method, defaulting to null when not present.

web/core/components/issues/issue-detail/sidebar.tsx (3)

60-60: Default initialization of customProperties is good.

Using issue?.custom_properties || [] ensures that we always have an array to work with, even if the custom properties are undefined.


345-357: Good implementation for displaying additional properties.

The map function correctly displays the additional properties when they exist on the issue. The null check ensures that undefined properties aren't rendered.


359-365: Ensure CustomProperties component gracefully handles different property formats.

While the component receives the customProperties with an Array check, it's not clear from the code shown whether the CustomProperties component itself properly handles all edge cases (like invalid property structures).

Please check the implementation of the CustomProperties component to ensure it handles edge cases appropriately, particularly:

  • When customProperties is an empty array
  • When an individual property doesn't match the expected structure
  • When the issue_type_id is null or invalid
apiserver/plane/api/views/member.py (6)

22-22: Good addition of the Profile model import.

The import of the Profile model is appropriate for the new profile-related functionality being added in this file.


66-71: Simplified validation logic.

The validation logic has been simplified to only check for email presence, removing the display_name requirement. The error message has been updated to reflect this change.


94-94: Good practice: Converting email to lowercase when querying.

Converting the email to lowercase before querying the database is a good practice to ensure case-insensitive email lookups.


117-123: Well-structured user data dictionary.

The user data is now organized in a clear dictionary structure before being used for user creation, improving code readability and maintainability.


138-138: Good refactoring: Using helper method for workspace member creation.

Refactoring the workspace member creation into a separate helper method improves code organization and reusability.


142-142: Good refactoring: Using helper method for project member creation.

Refactoring the project member creation into a separate helper method improves code organization and reusability.

apiserver/Dockerfile.api (4)

33-36: Good addition of Flower for Celery monitoring.

Adding Flower for Celery monitoring is a good enhancement, but be aware that setting FLOWER_UNAUTHENTICATED_API=true could pose security risks in production environments.

Consider implementing authentication for Flower in production environments to prevent unauthorized access to monitoring data.


51-52: Updated port exposure to include Flower UI port.

Exposing both the API and Flower UI ports is necessary for the new functionality.


54-61: Good use of build arguments for environment file handling.

Using build arguments to handle environment file paths is a flexible approach that allows for different configurations in different environments.


63-65:

Details

❓ Verification inconclusive

Conditional database migration execution.

The conditional execution of database migrations based on ENV_TYPE is a good approach to ensure migrations run only in the appropriate environment.


🏁 Script executed:

#!/bin/bash
# Check if ENV_TYPE is declared anywhere in the Dockerfile or related configuration
grep -r "ENV ENV_TYPE" --include="*.yml" --include="Dockerfile*" .

Length of output: 68


Action Required: Verify External ENV_TYPE Definition

The conditional execution of database migrations based on ENV_TYPE is a sound technique. However, our initial search did not reveal any explicit definition of ENV_TYPE in Dockerfiles or YAML configs, indicating that this variable is likely expected to be provided externally (for example, via runtime environment variables or CI/CD settings). Please ensure that:

  • ENV_TYPE is appropriately set in your deployment or runtime environment.
  • There is clear documentation on where and how ENV_TYPE is defined to avoid any unintended behavior during container startup.

If ENV_TYPE is managed externally and this design is intentional, no changes are needed. Otherwise, consider providing a default definition or including it in your configuration files for clarity.

web/core/components/issues/issue-layouts/filters/header/filters/additional-properties.tsx (1)

10-16: Well-defined Props interface.

The Props interface is well-defined with appropriate types for each property.

web/core/constants/spreadsheet.ts (3)

14-14: Good import of the Tags icon.

The Tags icon is appropriately imported for use in the new property definitions.


36-36: Good component import for property display.

The SpreadsheetStandardPropertyColumn import is necessary to support the new property definitions.


288-297: Property list additions.

The additions to SPREADSHEET_PROPERTY_LIST are necessary to include the new properties in the available options.

web/core/components/issues/peek-overview/properties.tsx (2)

61-62: Confirm default value for issue_type_id.

Using a hard-coded fallback ("afd30f86-5ae5-428c-aa3a-e633ea973740") might cause unexpected behavior or indicates a placeholder that needs verification.

Would you like to confirm whether this is the correct default value or if it should be dynamically derived from the workspace or project settings?


359-365: Looks good overall.

Rendering CustomProperties here cleanly integrates with the rest of the component.

web/core/components/issues/custom-properties.tsx (1)

158-188: Validate potential key collisions in mergedCustomProperties.map(...).

You are using element.key as the React key. If your API or local data ever include duplicate keys, React will issue a warning and render updates incorrectly. Make sure the server enforces unique property keys per issue type or consider appending a unique identifier to avoid potential collisions.

apiserver/plane/api/serializers/issue.py (1)

314-331: Confirm whether deleting then recreating all custom properties is intentional.

In the update method, existing IssueCustomProperty entries are deleted and replaced with the new list. If partial updates are desired, consider a more selective approach that updates or inserts only the changed properties, preserving the others.

apiserver/plane/db/models/issue.py (2)

79-88: Enhanced display properties look good.

Adding these references (trip_reference_number, reference_number, hub_code, etc.) expands the displayed attributes. The JSON field remains consistent and no immediate issues appear.


733-755: New IssueCustomProperty model design appears solid.

The structure is clear, with a straightforward relationship to Issue and IssueTypeCustomProperty. The naming is consistent, and the default ordering meets typical use cases. No further issues identified.

apiserver/plane/bgtasks/issue_activities_task.py (2)

394-394: Great flexibility with dynamic verb usage.

Using the verb=verb parameter instead of a hard-coded string provides better flexibility and reusability in track_assignees.


1740-1741: Nice addition of custom_property mappings.

Adding "custom_property.activity.updated" and "custom_property.activity.created" to ACTIVITY_MAPPER ensures consistency with other tracked changes.

apiserver/plane/api/views/webhook.py (5)

1-14: Imports appear fine.

The chosen imports are minimal and relevant for the functionalities required.


40-78: Efficient retrieval of single vs. multiple webhooks.

Differentiating between a single webhook (by pk) and multiple webhooks is straightforward. Verify that only authorized users can view workspace-wide webhooks.


104-108: Delete method is straightforward.

Uses the correct HTTP 204 status code to indicate success and clearly handles resource removal.


110-119: Regenerating secret keys with admin permission.

Using @allow_permission with allowed_roles=[ROLE.ADMIN] ensures that only admins can regenerate the secret key, which is solid from a security standpoint.


121-130: Restrict logs to admin roles.

Retrieving logs for a specific webhook is well-implemented, and the permission check helps ensure only authorized users can access logs.

apiserver/plane/api/views/search.py (6)

1-13: Imports look aligned with required modules.

No issues detected with the chosen imports.


29-36: Clear docstring for GlobalSearchEndpoint.

The docstring provides a concise overview of the endpoint’s responsibility and functionality.


50-66: Consistent approach for project filtering.

The logic for including archived_at__isnull=True and checking active memberships is aligned with the rest of the application.


107-131: Cycle filtering logic aligns with other sections.

The approach to check for active members and non-archived projects is consistent and looks solid.


157-210: Subquery usage for project-page associations is commendable.

The use of OuterRef and Subquery to fetch the project ID is elegant. If handling large data sets, confirm that necessary indexes are present for performance.


211-235: Cohesive approach for filtering IssueView.

The inclusion of active members and non-archived projects is consistent. Watch out for potential performance bottlenecks if the dataset grows large.

demo.Jenkinsfile (3)

95-124: Parallel builds look good.

The parallel Docker image builds are well-structured. The use of dockerBuildArgs in the API service build is clear and reduces repetition. No issues found here.


129-156: Efficient registry push.

Parallel push to the registry is well-organized, matching the parallel build strategy. No concerns with correctness.


158-228: Deployment steps are clear.

Deploying the services in parallel to ECS for each component is a solid approach for quick rollouts. Logging and naming conventions are consistent. Looks good!

apiserver/plane/api/views/issue.py (1)

358-361: Confirm created_by assignment logic.

The code only assigns issue.created_by_id if issue.created_by is None. Ensure all relevant calls pass a valid user ID or an override is not required. Otherwise, you might inadvertently miss logging the actual creator.

Do you want a script to verify all usage of issue.created_by and ensure consistent assignment throughout the codebase?

apiserver/plane/authentication/views/app/magic.py (3)

65-70: Generate fallback emails carefully.

Using username + "@plane-shipsy.com" as a fallback is acceptable, but ensure that username is always provided or validated. Otherwise, this could produce invalid email addresses if username is empty or malformed.


79-79: Token in response is acceptable if ephemeral.

Returning the token in plain text suits a short-lived magic link approach, but confirm that each token is single-use or short-lived. Otherwise, consider rotating or securely storing it to mitigate replay attacks.


88-101: Workspace auto-creation logic is well-designed.

Automatically adding the user and admin to the default workspace and project upon sign-in appears consistent with the product’s requirement. No issues found here.


useEffect(() => {
console.log(pathname, 'pathname');
window.parent.postMessage({ type: "ROUTE_CHANGE", path: pathname }, "*");
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add origin verification to window messaging for security.

The current implementation accepts messages from any origin (*) and doesn't verify the source of incoming messages. This is a potential security vulnerability that could lead to cross-site scripting (XSS) attacks.

-    window.parent.postMessage({ type: "ROUTE_CHANGE", path: pathname }, "*");
+    // Use a specific trusted origin instead of "*"
+    const trustedOrigin = process.env.NEXT_PUBLIC_TRUSTED_PARENT_ORIGIN || window.location.origin;
+    window.parent.postMessage({ type: "ROUTE_CHANGE", path: pathname }, trustedOrigin);

And for the message handler:

     const onIncomingMessage = async (event) => {
-      console.log('onIncomingMessage', event);
+      // Verify the origin of the message
+      const trustedOrigin = process.env.NEXT_PUBLIC_TRUSTED_PARENT_ORIGIN || window.location.origin;
+      if (event.origin !== trustedOrigin) return;
+      
       if (event.data.type === "PLANE_SIGN_OUT") {
         try {
           await handleSignOut();
-          window.parent.postMessage({ type: "PLANE_SIGN_OUT_SUCCESS", path: pathname }, "*");
+          window.parent.postMessage({ type: "PLANE_SIGN_OUT_SUCCESS", path: pathname }, trustedOrigin);
         } catch (err) {}
       }
     };

Also applies to: 58-65

]

def get_queryset(self):
print(self.kwargs.get("project_id"))
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove debug print statement before deploying to production.

The added print statement is likely for debugging purposes. Using a proper logging mechanism would be more appropriate in a production environment.

-    print(self.kwargs.get("project_id"))
+    # Use Django's logging framework instead
+    import logging
+    logger = logging.getLogger(__name__)
+    logger.debug("Processing project_id: %s", self.kwargs.get("project_id"))
📝 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
print(self.kwargs.get("project_id"))
# Use Django's logging framework instead
import logging
logger = logging.getLogger(__name__)
logger.debug("Processing project_id: %s", self.kwargs.get("project_id"))

rm -rf $PLANE_TEMP_CODE_DIR
mkdir -p $PLANE_TEMP_CODE_DIR
REPO=https://github.com/makeplane/plane.git
REPO=https://github.com/shipsy/plane.git
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Repository URL has been changed to a different organization.

The repository URL has been changed from the original makeplane/plane.git to shipsy/plane.git. This change may have implications for maintenance, security updates, and compatibility.

Please confirm if this change is intentional and aligns with your deployment strategy. If this is a temporary change for development purposes, it should be reverted before merging to production.


Below is a shell script to search for both the legacy and new repository URLs across the repository and display the context around line 185 in deploy/selfhost/install.sh for further verification:

Please run this script to confirm whether the change from makeplane/plane.git to shipsy/plane.git is consistent throughout the codebase and intentional.


🏁 Script executed:

#!/bin/bash
# Search for the legacy repository URL in the entire repository
echo "Searching for legacy repository URL (https://github.com/makeplane/plane.git):"
rg "https://github.com/makeplane/plane.git" -n .

# Search for the new repository URL in the entire repository
echo "Searching for new repository URL (https://github.com/shipsy/plane.git):"
rg "https://github.com/shipsy/plane.git" -n .

# Display context around line 185 in the install.sh file
echo "Displaying context for deploy/selfhost/install.sh (lines 180-190):"
sed -n '180,190p' deploy/selfhost/install.sh

Length of output: 1345


Repository URL Change – Confirm Consistency Across the Codebase

The deployment script (deploy/selfhost/install.sh, line 185) now sets

REPO=https://github.com/shipsy/plane.git

which differs from the repository URL referenced in other files (e.g., package.json, README.md, and CONTRIBUTING.md still point to https://github.com/makeplane/plane.git). This inconsistency may lead to issues with clone operations, documentation accuracy, and overall maintenance.

  • Confirm if the change to the new URL (shipsy/plane.git) is an intentional part of a migration strategy.
  • If intentional, please update all references (including in documentation and configuration files) to ensure consistency.
  • If the change was temporary or unintentional, revert the URL in the deployment script to match the legacy URL.

ssl_cert_reqs=None,
)
else:
print("redis url: ", settings.REDIS_URL)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove debug print statement containing potentially sensitive information.

Printing the Redis URL to console could expose sensitive connection details including passwords in logs. This is a security risk in production environments.

-    print("redis url: ", settings.REDIS_URL)
+    # Use Django's logging framework with appropriate log level instead
+    import logging
+    logger = logging.getLogger(__name__)
+    # Log only the host, not the full URL with credentials
+    parsed_url = urlparse(settings.REDIS_URL)
+    logger.debug("Connecting to Redis at: %s:%s", parsed_url.hostname, parsed_url.port)

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

Comment on lines +20 to 21
"workspaces/<str:slug>/projects/<str:project_id>/archive/",
ProjectArchiveUnarchiveAPIEndpoint.as_view(),
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Ensure proper project_id validation

Changing from uuid:project_id to str:project_id removes automatic UUID format validation. Make sure that the ProjectArchiveUnarchiveAPIEndpoint view properly validates the format of incoming project IDs to maintain data integrity.


🏁 Script executed:

#!/bin/bash
# Check if the ProjectAPIEndpoint and ProjectArchiveUnarchiveAPIEndpoint contain validation for project IDs

echo "Checking validation in ProjectAPIEndpoint view:"
rg -A 10 "class ProjectAPIEndpoint" --type py

echo "Checking validation in ProjectArchiveUnarchiveAPIEndpoint view:"
rg -A 10 "class ProjectArchiveUnarchiveAPIEndpoint" --type py

echo "Looking for any UUID validation in these views:"
rg "UUID|uuid" -C 3 --type py apiserver/plane/api/views/project.py

Length of output: 1968


ProjectID Validation Missing in Archive Endpoint

Changing the URL parameter from uuid:project_id to str:project_id removes Django’s built-in UUID validation. Our verification confirms that neither ProjectArchiveUnarchiveAPIEndpoint nor related views explicitly validate that project_id adheres to UUID formatting before using it in database queries. This could lead to unexpected errors or security issues if malformed IDs are provided.

  • Action Required: Explicitly validate the project_id (for example, by using Python's UUID conversion with proper exception handling or a regex check) in the post method of ProjectArchiveUnarchiveAPIEndpoint (located in apiserver/plane/api/views/project.py).

Comment on lines +18 to +21
export const FilterAdditionalProperties: React.FC<Props> = observer((props) => {
const { workspaceSlug, projectId } = useParams();
const { appliedFilters, handleUpdate, searchQuery, additionalPropertyTitle, additionalPropertyKey } = props;
const workspaceService = new WorkspaceService(API_BASE_URL);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Potential type safety issue with useParams.

The component directly accesses workspaceSlug and projectId from useParams() without checking for null/undefined values, which could lead to runtime errors.

- const { workspaceSlug, projectId } = useParams();
+ const params = useParams();
+ const workspaceSlug = params?.workspaceSlug;
+ const projectId = params?.projectId;
+ 
+ if (!workspaceSlug || !projectId) {
+   return <p className="text-xs italic text-custom-text-400">Missing workspace or project information</p>;
+ }
📝 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
export const FilterAdditionalProperties: React.FC<Props> = observer((props) => {
const { workspaceSlug, projectId } = useParams();
const { appliedFilters, handleUpdate, searchQuery, additionalPropertyTitle, additionalPropertyKey } = props;
const workspaceService = new WorkspaceService(API_BASE_URL);
export const FilterAdditionalProperties: React.FC<Props> = observer((props) => {
const params = useParams();
const workspaceSlug = params?.workspaceSlug;
const projectId = params?.projectId;
if (!workspaceSlug || !projectId) {
return <p className="text-xs italic text-custom-text-400">Missing workspace or project information</p>;
}
const { appliedFilters, handleUpdate, searchQuery, additionalPropertyTitle, additionalPropertyKey } = props;
const workspaceService = new WorkspaceService(API_BASE_URL);
// ... rest of the component logic
});

Comment on lines +71 to +107
const handleCustomPropertiesUpdate = async (updatedProperties: CustomProperty[]) => {
try {
const updateRequests = updatedProperties.map((property) => {
const customPropertyId = property?.id || "";
const apiUrl = `/api/v1/workspaces/${workspaceSlug}/issues/${issueId}/custom-properties/`;
if (customPropertyId) {
return axios.patch(
`${apiUrl}${customPropertyId}/`,
{ value: property.value },
{
headers: {
'x-api-key': 'TEST_API_TOKEN',
'Content-Type': 'application/json'
}
}
);
} else {
return axios.post(
apiUrl,
{
key: property.key,
value: property.value,
issue_type_custom_property: property.issue_type_custom_property,
},
{
headers: {
'x-api-key': 'TEST_API_TOKEN',
'Content-Type': 'application/json'
}
}
);
}
});
await Promise.all(updateRequests);
} catch (error) {
}
};
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Handle caught errors appropriately.

The catch block is empty, which may hide issues during runtime. Add robust error logging or handling to make debugging easier.

Here is a suggested fix:

-    } catch (error) {
-    }
+    } catch (error) {
+      console.error("Failed to update custom properties:", error);
+      // Optionally, display an in-app notification or fallback UI here.
+    }
📝 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
const handleCustomPropertiesUpdate = async (updatedProperties: CustomProperty[]) => {
try {
const updateRequests = updatedProperties.map((property) => {
const customPropertyId = property?.id || "";
const apiUrl = `/api/v1/workspaces/${workspaceSlug}/issues/${issueId}/custom-properties/`;
if (customPropertyId) {
return axios.patch(
`${apiUrl}${customPropertyId}/`,
{ value: property.value },
{
headers: {
'x-api-key': 'TEST_API_TOKEN',
'Content-Type': 'application/json'
}
}
);
} else {
return axios.post(
apiUrl,
{
key: property.key,
value: property.value,
issue_type_custom_property: property.issue_type_custom_property,
},
{
headers: {
'x-api-key': 'TEST_API_TOKEN',
'Content-Type': 'application/json'
}
}
);
}
});
await Promise.all(updateRequests);
} catch (error) {
}
};
const handleCustomPropertiesUpdate = async (updatedProperties: CustomProperty[]) => {
try {
const updateRequests = updatedProperties.map((property) => {
const customPropertyId = property?.id || "";
const apiUrl = `/api/v1/workspaces/${workspaceSlug}/issues/${issueId}/custom-properties/`;
if (customPropertyId) {
return axios.patch(
`${apiUrl}${customPropertyId}/`,
{ value: property.value },
{
headers: {
'x-api-key': 'TEST_API_TOKEN',
'Content-Type': 'application/json'
}
}
);
} else {
return axios.post(
apiUrl,
{
key: property.key,
value: property.value,
issue_type_custom_property: property.issue_type_custom_property,
},
{
headers: {
'x-api-key': 'TEST_API_TOKEN',
'Content-Type': 'application/json'
}
}
);
}
});
await Promise.all(updateRequests);
} catch (error) {
console.error("Failed to update custom properties:", error);
// Optionally, display an in-app notification or fallback UI here.
}
};

Comment on lines +79 to +103
def patch(self, request, slug, pk):
webhook = Webhook.objects.get(workspace__slug=slug, pk=pk)
serializer = WebhookSerializer(
webhook,
data=request.data,
context={request: request},
partial=True,
fields=(
"id",
"url",
"is_active",
"created_at",
"updated_at",
"project",
"issue",
"cycle",
"module",
"issue_comment",
),
)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential bug in serializer context.

At line 85, you’re passing context={request: request} instead of {"request": request}, causing the 'request' key to be the request object itself. This likely breaks the serializer’s logic. Proposed fix:

-        context={request: request},
+        context={"request": request},
📝 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
def patch(self, request, slug, pk):
webhook = Webhook.objects.get(workspace__slug=slug, pk=pk)
serializer = WebhookSerializer(
webhook,
data=request.data,
context={request: request},
partial=True,
fields=(
"id",
"url",
"is_active",
"created_at",
"updated_at",
"project",
"issue",
"cycle",
"module",
"issue_comment",
),
)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def patch(self, request, slug, pk):
webhook = Webhook.objects.get(workspace__slug=slug, pk=pk)
serializer = WebhookSerializer(
webhook,
data=request.data,
context={"request": request},
partial=True,
fields=(
"id",
"url",
"is_active",
"created_at",
"updated_at",
"project",
"issue",
"cycle",
"module",
"issue_comment",
),
)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Comment on lines +78 to +86
echo "Vault CONFIG: \${CONFIG}" # Debugging, remove in production
pwd
mkdir -p apiserver/${configStoragePath}
echo "\${CONFIG}" > apiserver/${configStoragePath}/.env
"""

// Debugging: Show the contents of the .env file (optional for development only)
sh "cat apiserver/${configStoragePath}/.env"

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid printing secrets to the console.

Currently, the pipeline prints the secret environment variable (CONFIG) via echo and also displays .env content explicitly for debugging. This is a security risk as it may expose secrets in CI logs. Consider removing or masking these prints in production to protect sensitive information.

-echo "Vault CONFIG: ${CONFIG}"   # Debugging, remove in production
...
-cat apiserver/${configStoragePath}/.env
+echo "Vault CONFIG: [REDACTED]"  # Secure alternative
...
+# Remove 'cat' command to avoid leaking secrets
📝 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
echo "Vault CONFIG: \${CONFIG}" # Debugging, remove in production
pwd
mkdir -p apiserver/${configStoragePath}
echo "\${CONFIG}" > apiserver/${configStoragePath}/.env
"""
// Debugging: Show the contents of the .env file (optional for development only)
sh "cat apiserver/${configStoragePath}/.env"
echo "Vault CONFIG: [REDACTED]" # Secure alternative
pwd
mkdir -p apiserver/${configStoragePath}
echo "${CONFIG}" > apiserver/${configStoragePath}/.env
"""
// Debugging: Show the contents of the .env file (optional for development only)
// Remove 'cat' command to avoid leaking secrets

current_instance = json.dumps(serializer.data, cls=DjangoJSONEncoder)
actor_id = str(request.user.id) if request.user else "Unknown"
issue_id_str = str(issue_id) if issue_id else "Unknown issue ID"
slug = slug=self.kwargs.get("slug")
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential bug in slug assignment.

slug = slug=self.kwargs.get("slug") is redefining slug with a named parameter, which results in slug being assigned a tuple or leading to unexpected behavior. It should likely be slug = self.kwargs.get("slug").

-slug = slug=self.kwargs.get("slug")
+slug = self.kwargs.get("slug")
📝 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
slug = slug=self.kwargs.get("slug")
slug = self.kwargs.get("slug")

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.

8 participants