10 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e30605d419
|
[WEB-7946] fix: add rate limiting to email/password sign-in and sign-up endpoints (#9335)
* fix: add rate limiting to email/password sign-in and sign-up endpoints All four password authentication views (app sign-in, app sign-up, space sign-in, space sign-up) extended django.views.View, so DRF's global AnonRateThrottle never ran and the endpoints accepted unlimited credential guesses with no friction (brute-force / credential stuffing, GHSA-349j). Add authentication_throttle_allows(request) at the top of each post() method — before any DB access — using the same AuthenticationThrottle already guarding the magic-code views. On rejection the view redirects with RATE_LIMIT_EXCEEDED, consistent with all other throttled auth endpoints. Default limit remains 10/minute, overridable via AUTHENTICATION_RATE_LIMIT. Co-authored-by: Plane AI <noreply@plane.so> * refactor: consolidate auth throttle into a decorator + add tests - Extract the repeated throttle-and-redirect block from the six redirect-flow auth views (email + magic, app + space) into a single throttle_auth_redirect decorator in rate_limit.py. Behaviour is unchanged: the throttle still runs before any DB access; brute-force traffic is rejected without a DB hit. - Add regression tests for the password sign-in/sign-up throttle on both app and space endpoints, mirroring the existing magic-code throttle tests. - Reset the shared AuthenticationThrottle bucket before every test in test_authentication.py. All auth endpoints share one per-IP throttle scope, so the newly-throttled password requests exhausted the budget mid-file and caused unrelated tests to trip RATE_LIMIT_EXCEEDED. --------- Co-authored-by: Plane AI <noreply@plane.so> Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com> |
||
|
|
ca3b48ef87
|
chore: upgrade Django 4.2 → 5.2 (#9325)
* chore(api): upgrade Django 4.2 → 5.2 and bump Django ecosystem deps Upgrade Django 4.2.30 LTS → 5.2.15 LTS and bump all Django-coupled dependencies to versions that officially support 5.2 (DRF 3.17.1, channels 4.3.2, django-cors-headers 4.9.0, django-filter 25.2, django-storages 1.14.6, django-redis 7.0.0, celery 5.5.3, django-celery-beat 2.9.0, django-celery-results 2.6.0, drf-spectacular 0.29.0, scout-apm 3.5.3, psycopg 3.3.4, whitenoise 6.12.0, django-debug-toolbar 6.0.0, pytest-django 4.12.0). OpenTelemetry set, django-crum and pytz held (already 5.2-compatible). Code changes the upgrade required: - urls.py: gate the debug-toolbar URL include on apps.is_installed(), since django-debug-toolbar 6.0 ships a model that errors when the app isn't in INSTALLED_APPS (test settings run DEBUG=True but don't install it). - migration 0122: state-only AlterField for three M2M fields using through_fields (Django 5.1 deconstruction normalization); sqlmigrate is a no-op, zero DB impact. - test_authentication.py: module-level autouse cache.clear() fixture to fix 8 pre-existing throttle test-isolation failures (identical on the 4.2 baseline) so the suite is green. Verified on python:3.12-alpine + Postgres 15.7: check clean, makemigrations --check clean, full migrate applies, pytest 393 passed. Adds the migration plan/audit write-up under apps/api/docs/. * fix(api): scope auth test cache reset to throttle keys only The module-wide _reset_auth_throttle_cache fixture called cache.clear(), wiping the entire shared Redis cache between tests. Replace it with targeted deletion of throttle_authentication_* keys (DRF SimpleRateThrottle history for AuthenticationThrottle) via cache.delete_pattern, keeping the same before/after cleanup. |
||
|
|
4fc79a2d7e
|
fix(security): block bot user logins (#9368)
Bot service accounts (User.is_bot=True, e.g. the WORKSPACE_SEED bot) are internal identities meant to act only through API tokens. Nothing stopped one from being driven through the interactive login flow if its email was known, letting a human assume a service identity. Reject bot accounts at the shared login chokepoint, Adapter.complete_login_or_signup(), right beside the existing deactivated-account check. This covers every interactive provider in one place: email/password, magic code, and all OAuth providers (Google, GitHub, GitLab, Gitea) across both the app and space surfaces. Bot API-token access is left untouched, since that is how bots are meant to operate. Also add a defense-in-depth is_bot guard to InstanceAdminSignInEndpoint, which mints its own admin session outside the chokepoint (a bot is never an InstanceAdmin today, so this is not currently reachable, but it closes the path regardless). Surface the rejection with a new dedicated error code BOT_USER_LOGIN_FORBIDDEN (5017), plumbed into the app and space frontend error helpers as well as the shared @plane/constants and @plane/utils packages (message map + banner-alert list) so any consumer of the shared auth-error handler renders it correctly. The admin path reuses the existing ADMIN_AUTHENTICATION_FAILED code so it discloses no bot-specific error. Add contract regression tests: a bot blocked via password and via magic code, a bot blocked at the admin sign-in endpoint, and a non-bot control that still logs in. |
||
|
|
b1c78fe4c8
|
fix(api): rate-limit magic-code verify, bound per-token attempts (GHSA-9pvm-fcf6-9234) (#9130)
* fix(api): rate-limit magic-code verification and bound per-token attempts
The magic-link sign-in / sign-up endpoints accept a 6-digit numeric code
(900k-value space, 600s TTL) but never increment a failure counter on a
wrong-code verify and extend django.views.View rather than DRF APIView,
so DRF's AuthenticationThrottle never runs against them. The space-side
generate endpoint also lacked throttle_classes. Combined, this allowed
an unauthenticated attacker who knew a victim's email to brute-force
the code within the TTL window and log in as the victim.
- Add MAX_VERIFY_ATTEMPTS=5 in MagicCodeProvider.set_user_data: failed
comparisons now persist verify_attempts in Redis under the remaining
TTL and, on hitting the limit, delete the key and raise
EMAIL_CODE_ATTEMPT_EXHAUSTED. This is the load-bearing fix - it caps
total attempts per issued token regardless of request rate.
- Add authentication_throttle_allows() so plain Django Views can apply
AuthenticationThrottle without converting to APIView (would change
CSRF + request-parsing semantics for the redirect-flow endpoints).
- Apply the throttle to MagicSignIn/UpEndpoint and the space variants;
add throttle_classes to MagicGenerateSpaceEndpoint to match its app
sibling.
Refs GHSA-9pvm-fcf6-9234.
* fix(api): make verify-attempt increment atomic, expose throttle rate via env
Address PR review feedback:
- Replace the JSON read-modify-write of verify_attempts with a Lua
EVAL script that INCRs a dedicated counter key and EXPIREs it only
on the first increment. The previous round-trip was racy: parallel
wrong-code requests could read the same value and both write the
same incremented count, letting an attacker exceed MAX_VERIFY_ATTEMPTS
under concurrency. Counter is now reset on each new token issuance
and cleared on successful verify / exhaustion.
- Make AuthenticationThrottle.rate configurable via the
AUTHENTICATION_RATE_LIMIT env var (default 10/minute, down from 30
to tighten the budget on unauth auth-adjacent endpoints). Document
it in deployments/aio and deployments/cli variables.env.
* test(api): cover magic-code attempt cap, counter reset, and auth throttle
Add the contract tests called out in the PR test plan:
- TestMagicSignInVerifyAttempts:
- test_exhausted_after_max_wrong_attempts: after MAX_VERIFY_ATTEMPTS
wrong codes the next verify redirects with EMAIL_CODE_ATTEMPT_
EXHAUSTED_SIGN_IN and both Redis keys are deleted; a follow-up
verify reports EXPIRED.
- test_counter_increments_on_each_wrong_attempt: the dedicated
verify_attempts counter advances by exactly one per wrong POST,
matching the atomic Lua INCR.
- test_counter_resets_on_token_regeneration: regenerating the
magic-link clears the counter so the user isn't pre-locked-out by
a prior session's wrong attempts.
- TestMagicSignUpVerifyAttempts.test_signup_exhausted_after_max_wrong_attempts:
the sign-up endpoint returns EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_UP on
the exhausting attempt.
- TestAuthenticationThrottle: exercises authentication_throttle_allows
on the plain-View redirect-flow endpoints by patching the rate down
and asserting RATE_LIMIT_EXCEEDED is appended to the redirect URL
once the per-IP budget is exceeded, for both magic-sign-in and
magic-sign-up.
Each new class clears Django cache (DRF throttle storage) and the
per-email Redis keys around every test so runs are independent.
* fix(api): clamp remaining_ttl to >=1 for verify-attempt counter EXPIRE
ri.ttl() returns 0 when the token has less than one second remaining
(Redis floors to whole seconds). The previous clamp only caught
None and < 0, so a sub-second TTL would pass through and the Lua
script's EXPIRE counter 0 would immediately delete the key — letting
an attacker bypass MAX_VERIFY_ATTEMPTS during the final second of the
token's life. Switch the comparison to <= 0.
Narrow real-world impact (sub-second window, throttle still bounds
the rate) but the cap should hold regardless of timing.
|
||
|
|
9f77ea5ebb
|
fix: Add docker pytest runner and fix bugs the suite surfaced (#9138)
* chore(api): add docker compose test runner
Adds docker-compose-test.yml at the repo root that boots an isolated
postgres / valkey / rabbitmq / minio stack with health checks and tmpfs
data dirs, then runs pytest against it and exits. Includes a usage doc
under apps/api/tests/RUNNING_TESTS.md and a pointer in AGENTS.md.
Prereq: ./setup.sh (generates apps/api/.env).
Usage:
docker compose -f docker-compose-test.yml up --build \
--abort-on-container-exit --exit-code-from api-tests
docker compose -f docker-compose-test.yml down -v
* fix(api): correct bugs surfaced by the pytest suite
Five small bugs caught by enabling the pytest contract suite end-to-end.
Each is independently justifiable:
- api/serializers/cycle.py + api/views/cycle.py: CycleCreateSerializer.validate
required project_id in the request body, but the view only ever passes
it through the URL kwarg. Cycle create/update via the public API was
returning 400 "Project ID is required". Read project_id from
serializer context (passed by the view) in addition to body/instance.
- app/views/api.py: ApiTokenEndpoint.get(pk) and patch(pk) did not filter
out is_service=True tokens, so a user could read and modify service
tokens through the user token endpoint. The list mode and delete
already filter is_service=False; aligned the other two.
- bgtasks/work_item_link_task.py: validate_url_ip checked hostname before
scheme, so file:///etc/passwd raised "No hostname found" instead of
the documented "Only HTTP and HTTPS" error. Swapped the order so the
scheme guard matches the docstring intent.
- utils/path_validator.py: get_allowed_hosts used `WEB_URL or APP_BASE_URL`
so when both are configured to different hosts (the standard local
setup: WEB_URL=:8000, APP_BASE_URL=:3000), only one was added to the
allow-list. Redirects to APP_BASE_URL then had their next_path stripped
because the host wasn't allowed. Include every configured base URL.
* chore(api): align pytest tests with current behavior, clear warnings
Test-side fixes paired with the product fixes in the previous commit, plus
deprecation cleanup that drops the test run from 104 warnings to 0.
Tests:
- tests/contract/api/test_cycles.py: project fixture sets cycle_view=True;
the Project model defaults the flag to False, so cycle create/update
always tripped "Cycles are not enabled for this project".
- tests/contract/app/test_authentication.py: next_path uses "/workspaces"
(validate_next_path rejects values without a leading slash and returns
empty, which dropped the path from the redirect URL).
- tests/unit/bg_tasks/test_copy_s3_objects.py: mocked sync_with_external_service
now returns description_json; the task unconditionally writes the value
back to the Issue, and Issue.description_json is NOT NULL on UPDATE.
- tests/unit/utils/test_url.py: three length-limit tests placed the URL at
char 970+ on a single line, which contains_url truncates away as ReDoS
defense (500-char per-line cap). Restructured to keep test intent intact
while staying inside the per-line window.
Warning cleanup (104 → 0):
- settings/common.py: removed USE_L10N=True (deprecated in Django 4.0,
removed in 5.0; default is True).
- celery.py, settings/local.py, settings/production.py: pythonjsonlogger
moved jsonlogger → json; update the import / formatter path.
|
||
|
|
02d0ee3e0f
|
chore: add copyright (#8584)
* feat: adding new copyright info on all files * chore: adding CI |
||
|
|
9237f568dd
|
[WEB-5044] fix: ruff lint and format errors (#7868)
* fix: lint errors * fix: file formatting * fix: code refactor |
||
|
|
514686d9d5
|
[WEB-4045] feat: restructuring of the external APIs for better maintainability (#7477)
* Basic setup for drf-spectacular * Updated to only handle /api/v1 endpoints * feat: add asset and user endpoints with URL routing - Introduced new asset-related endpoints for user assets and server assets, allowing for asset uploads and management. - Added user endpoint to retrieve current user information. - Updated URL routing to include new asset and user patterns. - Enhanced issue handling with a new search endpoint for issues across multiple fields. - Expanded member management with a new endpoint for workspace members. * Group endpoints by tags * Detailed schema definitions and examples for asset endpoints * Removed unnecessary extension * Specify avatar_url field separately * chore: add project docs * chore: correct all errors * chore: added open spec in work items * feat: enhance cycle API endpoints with detailed OpenAPI specifications - Updated CycleAPIEndpoint and CycleIssueAPIEndpoint to include detailed OpenAPI schema definitions for GET, POST, PATCH, and DELETE operations. - Specified allowed HTTP methods for each endpoint in the URL routing. - Improved documentation for cycle creation, updating, and deletion, including request and response examples. * chore: added open spec in labels * chore: work item properties * feat: enhance API endpoints with OpenAPI specifications and HTTP method definitions - Added detailed OpenAPI schema definitions for various API endpoints including Intake, Module, and State. - Specified allowed HTTP methods for each endpoint in the URL routing for better clarity and documentation. - Improved request and response examples for better understanding of API usage. - Introduced unarchive functionality for cycles and modules with appropriate endpoint definitions. * chore: run formatter * Removed unnecessary settings for authentication * Refactors OpenAPI documentation structure Improves the organization and maintainability of the OpenAPI documentation by modularizing the `openapi_spec_helpers.py` file. The changes include: - Migrates common parameters, responses, examples, and authentication extensions to separate modules. - Introduces helper decorators for different endpoint types. - Updates view imports to use the new module paths. - Removes the legacy `openapi_spec_helpers.py` file. This refactoring results in a more structured and easier-to-maintain OpenAPI documentation setup. * Refactor OpenAPI endpoint specifications - Removed unnecessary parameters from the OpenAPI documentation for various endpoints in the asset, cycle, and project views. - Updated request structures to improve clarity and consistency across the API documentation. - Enhanced response formatting for better readability and maintainability. * Enhance API documentation with detailed endpoint descriptions Updated various API endpoints across the application to include comprehensive docstrings that clarify their functionality. Each endpoint now features a summary and detailed description, improving the overall understanding of their purpose and usage. This change enhances the OpenAPI specifications for better developer experience and documentation clarity. * Enhance API serializers and views with new request structures - Added new serializers for handling cycle and module issue requests, including `CycleIssueRequestSerializer`, `TransferCycleIssueRequestSerializer`, `ModuleIssueRequestSerializer`, and intake issue creation/updating serializers. - Updated existing serializers to improve clarity and maintainability, including the `UserAssetUploadSerializer` and `IssueAttachmentUploadSerializer`. - Refactored API views to utilize the new serializers, enhancing the request handling for cycle and intake issue endpoints. - Improved OpenAPI documentation by replacing inline request definitions with serializer references for better consistency and readability. * Refactor OpenAPI documentation and endpoint specifications - Replaced inline schema definitions with dedicated decorators for various endpoint types, enhancing clarity and maintainability. - Updated API views to utilize new decorators for user, cycle, intake, module, and project endpoints, improving consistency in OpenAPI documentation. - Removed unnecessary parameters and responses from endpoint specifications, streamlining the documentation for better readability. - Enhanced the organization of OpenAPI documentation by modularizing endpoint-specific decorators and parameters. * chore: correct formatting * chore: correct formatting for all api folder files * refactor: clean up serializer imports and test setup - Removed unused `StateLiteSerializer` import from the serializer module. - Updated test setup to include a noqa comment for the `django_db_setup` fixture, ensuring clarity in the code. - Added missing commas in user data dictionary for consistency. * feat: add project creation and update serializers with validation - Introduced `ProjectCreateSerializer` and `ProjectUpdateSerializer` to handle project creation and updates, respectively. - Implemented validation to ensure project leads and default assignees are members of the workspace. - Updated API views to utilize the new serializers for creating and updating projects, enhancing request handling. - Added OpenAPI documentation references for the new serializers in the project API endpoints. * feat: update serializers to include additional read-only fields * refactor: rename intake issue serializers and enhance structure - Renamed `CreateIntakeIssueRequestSerializer` to `IntakeIssueCreateSerializer` and `UpdateIntakeIssueRequestSerializer` to `IntakeIssueUpdateSerializer` for clarity. - Introduced `IssueSerializer` for nested issue data in intake requests, improving the organization of serializer logic. - Updated API views to utilize the new serializer names, ensuring consistency across the codebase. * refactor: rename issue serializer for intake and enhance API documentation - Renamed `IssueSerializer` to `IssueForIntakeSerializer` for better clarity in the context of intake issues. - Updated references in `IntakeIssueCreateSerializer` and `IntakeIssueUpdateSerializer` to use the new `IssueForIntakeSerializer`. - Added OpenAPI documentation for the `get_workspace_work_item` endpoint, detailing parameters and responses for improved clarity. * chore: modules and cycles serializers * feat: add new serializers for label and issue link management - Introduced `LabelCreateUpdateSerializer`, `IssueLinkCreateSerializer`, `IssueLinkUpdateSerializer`, and `IssueCommentCreateSerializer` to enhance the handling of label and issue link data. - Updated existing API views to utilize the new serializers for creating and updating labels, issue links, and comments, improving request handling and validation. - Added `IssueSearchSerializer` for searching issues, streamlining the search functionality in the API. * Don't consider read only fields as required * Add setting to separate request and response definitions * Fixed avatar_url warning on openapi spec generation * Made spectacular disabled by default * Moved spectacular settings into separate file and added detailed descriptions to tags * Specify methods for asset urls * Better server names * Enhance API documentation with summaries for various endpoints - Added summary descriptions for user asset, cycle, intake, issue, member, module, project, state, and user API endpoints to improve clarity and usability of the API documentation. - Updated the OpenAPI specifications to reflect these changes, ensuring better understanding for developers interacting with the API. * Add contact information to OpenAPI settings - Included contact details for Plane in the OpenAPI settings to enhance API documentation and provide developers with a direct point of contact for support. - This addition aims to improve the overall usability and accessibility of the API documentation. * Reordered tags and improved description relavancy * Enhance OpenAPI documentation for cycle and issue endpoints - Added response definitions for the `get_cycle_issues` and `delete_cycle_issue` methods in the CycleIssueAPIEndpoint to clarify expected outcomes. - Included additional response codes for the IssueSearchEndpoint to handle various error scenarios, improving the overall API documentation and usability. * Enhance serializer documentation across multiple files - Updated docstrings for various serializers including UserAssetUploadSerializer, AssetUpdateSerializer, and others to provide clearer descriptions of their functionality and usage. - Improved consistency in formatting and language across serializer classes to enhance readability and maintainability. - Added detailed explanations for new serializers related to project, module, and cycle management, ensuring comprehensive documentation for developers. * Refactor API endpoints for cycles, intake, modules, projects, and states - Replaced existing API endpoint classes with more descriptive names such as CycleListCreateAPIEndpoint, CycleDetailAPIEndpoint, IntakeIssueListCreateAPIEndpoint, and others to enhance clarity. - Updated URL patterns to reflect the new endpoint names, ensuring consistency across the API. - Improved documentation and method summaries for better understanding of endpoint functionalities. - Enhanced query handling in the new endpoint classes to streamline data retrieval and improve performance. * Refactor issue and label API endpoints for clarity and functionality - Renamed existing API endpoint classes to more descriptive names such as IssueListCreateAPIEndpoint, IssueDetailAPIEndpoint, LabelListCreateAPIEndpoint, and LabelDetailAPIEndpoint to enhance clarity. - Updated URL patterns to reflect the new endpoint names, ensuring consistency across the API. - Improved method summaries and documentation for better understanding of endpoint functionalities. - Streamlined query handling in the new endpoint classes to enhance data retrieval and performance. * Refactor asset API endpoint methods and introduce new status enums - Updated the GenericAssetEndpoint to only allow POST requests for asset creation, removing the GET method. - Modified the get method to require asset_id, ensuring that asset retrieval is always tied to a specific asset. - Added new IntakeIssueStatus and ModuleStatus enums to improve clarity and management of asset and module states. - Enhanced OpenAPI settings to include these new enums for better documentation and usability. * enforce naming convention * Added LICENSE to openapi spec * Enhance OpenAPI documentation for various API endpoints - Updated API endpoints in asset, cycle, intake, issue, module, project, and state views to include OpenApiRequest and OpenApiExample for better request documentation. - Added example requests for creating and updating resources, improving clarity for API consumers. - Ensured consistent use of OpenApi utilities across all relevant endpoints to enhance overall API documentation quality. * Enhance OpenAPI documentation for various API endpoints - Added detailed descriptions to multiple API endpoints across asset, cycle, intake, issue, module, project, state, and user views to improve clarity for API consumers. - Ensured consistent documentation practices by including descriptions that outline the purpose and functionality of each endpoint. - This update aims to enhance the overall usability and understanding of the API documentation. * Update OpenAPI examples and enhance project queryset logic - Changed example fields in OpenAPI documentation for issue comments from "content" to "comment_html" to reflect the correct structure. - Introduced a new `get_queryset` method in the ProjectDetailAPIEndpoint to filter projects based on user membership and workspace, while also annotating additional project-related data such as total members, cycles, and modules. - Updated permission checks to use the correct attribute name for project identifiers, ensuring accurate permission handling. * Enhance OpenAPI documentation and add response examples - Updated multiple API endpoints across asset, cycle, intake, issue, module, project, state, and user views to include new OpenApiResponse examples for better clarity on expected outcomes. - Introduced new parameters for project and issue identifiers to improve request handling and documentation consistency. - Enhanced existing responses with detailed examples to aid API consumers in understanding the expected data structure and error handling. - This update aims to improve the overall usability and clarity of the API documentation. * refactor: update terminology from 'issues' to 'work items' across multiple API endpoints for consistency and clarity * use common timezones from pytz for choices * Moved the openapi utils to the new folder structure * Added exception logging in GenericAssetEndpoint to improve error handling * Fixed code rabbit suggestions * Refactored IssueDetailAPIEndpoint to streamline issue retrieval and response handling, removing redundant external ID checks and custom ordering logic. --------- Co-authored-by: pablohashescobar <nikhilschacko@gmail.com> Co-authored-by: NarayanBavisetti <narayan3119@gmail.com> |
||
|
|
6ce700fd5d
|
chore: format files using prettier (#7364)
* chore: format files using prettier * chore: api server files formatted |
||
|
|
fdbe4c2ca6
|
chore: rename server to api (#7342) |
Renamed from apps/server/plane/tests/contract/app/test_authentication.py (Browse further)