Commit Graph

1947 Commits

Author SHA1 Message Date
Atul Tameshwari
52478d58d4 fix: oxfmt 2026-06-29 10:47:03 +05:30
Atul Tameshwari
ca6d480dd8 Merge branch 'preview' into git-248/components-consolidation-core-components 2026-06-29 09:18:58 +05:30
Rahul Cheryala
90ae8457d0 [GIT-239 | GIT-240] refactor: hooks and constants consolidation to core (#9204) 2026-06-26 20:36:52 +05:30
Manish Gupta
1e8f3630c7 [WEB-7787] fix(auth): restore activation flow and narrow deactivation guard (#9304)
* fix(auth): restore activation flow and narrow deactivation guard (GHSA-rmmf-rj2q-3rrg)

PR #9290 introduced two regressions in adapter/base.py:

1. is_signup = bool(user) was inverted — True when the user EXISTS means
   the IDP sync ran on signup instead of login, and the callback received
   the wrong value. Fixed to is_signup = not bool(user) matching EE.

2. The deactivation check blocked ALL inactive users, including accounts
   provisioned with is_active=False that have never completed a first
   login. Fixed by adding `and user.last_login_time is not None` — only
   accounts that have previously logged in (and were then explicitly
   deactivated by an admin) are rejected. Provisioned/never-logged-in
   accounts still pass through to save_user_data().

3. Restore is_active=True and user_activation_email in save_user_data()
   so provisioned accounts are properly activated on first login.

Co-authored-by: Plane AI <noreply@plane.so>

* fix(auth): save before email, use last_logout_time as deactivation discriminator

Two CR fixes on PR #9304:

1. save_user_data(): capture was_inactive flag, save() first, then send
   activation email as a best-effort side-effect so a failed enqueue
   cannot abort account activation.

2. complete_login_or_signup(): switch deactivation discriminator from
   last_login_time to last_logout_time. The deactivation endpoint always
   sets last_logout_time, making it a direct signal of explicit
   deactivation. A provisioned account that was never deactivated has
   last_logout_time=None and is correctly allowed through for first login,
   even if it also has no last_login_time.

Co-authored-by: Plane AI <noreply@plane.so>

---------

Co-authored-by: Plane AI <noreply@plane.so>
2026-06-24 14:40:24 +05:30
Manish Gupta
6c9dbb5043 [WEB-7787] fix(security): block deactivated user login and fix WorkspaceOwnerPermission (#9290)
GHSA-rmmf-rj2q-3rrg: save_user_data() was unconditionally setting
is_active=True on every login, silently reactivating any admin-deactivated
account. Fix: add an early guard in complete_login_or_signup() that raises
USER_ACCOUNT_DEACTIVATED (5019) before any session or save logic if the
existing user's is_active=False. Remove the is_active=True assignment and
the associated user_activation_email call from save_user_data(). Also
remove the now-unused user_activation_email and base_host imports.

GHSA-wjgv-cq7w-258v: WorkspaceOwnerPermission in both app/permissions/
and utils/permissions/ was filtering WorkspaceMember without is_active=True,
allowing a deactivated workspace owner/admin to retain API access. Add
is_active=True to both copies to match every other permission class.

Co-authored-by: Plane AI <noreply@plane.so>
2026-06-23 18:10:40 +05:30
Manish Gupta
cc3eb974f1 [WEB-7813] fix: prevent ORM order_by injection in issue and other endpoints (#9292)
* fix: prevent ORM order_by injection via user-supplied query params (GHSA-2r95, GHSA-w45q)

Add field-name allowlists and a sanitize_order_by() utility in order_queryset.py.
All allowlists are centralised there; each call site imports the named constant
so there are no inline sets scattered across view files.

- order_queryset.py: ISSUE_ORDER_BY_ALLOWLIST, INTAKE_ISSUE_ORDER_BY_ALLOWLIST,
  ACTIVITY_ORDER_BY_ALLOWLIST, PROJECT_ORDER_BY_ALLOWLIST, VIEW_ORDER_BY_ALLOWLIST,
  NOTIFICATION_ORDER_BY_ALLOWLIST + sanitize_order_by() utility; validation added
  at the top of order_issue_queryset() — fixes all callers including the
  unauthenticated ProjectIssuesPublicEndpoint (GHSA-w45q)
- api/views/cycle.py, api/views/module.py: cycle/module issue list endpoints
- api/views/issue.py: IssueActivity list and detail endpoints
- app/views/intake/base.py: IntakeIssue list
- app/views/view/base.py: saved-view list
- app/views/notification/base.py: notification paginator
- app/views/project/base.py: project list paginator
- app/views/user/base.py, app/views/workspace/user.py: activity paginators

Closes WEB-7813

Co-authored-by: Plane AI <noreply@plane.so>

* fix: harden sanitize_order_by against multi-dash malformed inputs

lstrip("-") stripped all leading dashes, allowing "--created_at" to
pass the allowlist check unchanged and reach .order_by() as a malformed
token (causing FieldError). Now strips only one leading dash; any
remaining dash prefix is rejected to the safe default.

Co-authored-by: Plane AI <noreply@plane.so>

---------

Co-authored-by: Plane AI <noreply@plane.so>
2026-06-23 18:02:52 +05:30
Manish Gupta
1acc69e816 [WEB-7805] fix: remove hardcoded SECRET_KEY from community deployment manifests (#9291)
* fix: remove hardcoded SECRET_KEY from community deployment manifests (GHSA-cmwv-pjmw-8483)

Replace the publicly-known default SECRET_KEY and LIVE_SERVER_SECRET_KEY values
in AIO and CLI community deployment manifests with a safe placeholder.

- deployments/aio: variables.env now ships with placeholder values;
  start.sh auto-generates a random key on first boot (or on upgrade from the old
  insecure default) and persists it in plane.env across restarts
- deployments/cli: variables.env ships with placeholder; docker-compose.yml
  fallbacks that referenced the publicly-known default are removed
- apps/api/plane/settings/common.py: SECRET_KEY resolution now uses `or`
  so an empty env var falls back to get_random_secret_key() (not ""); adds a
  startup warning if the known insecure default or placeholder is detected

Closes WEB-7805

Co-authored-by: Plane AI <noreply@plane.so>

* fix: use logger.critical instead of print for insecure SECRET_KEY warning

Address code review feedback — replace module-level print() with _logger.critical()
and move _logger definition before the SECRET_KEY block to avoid duplicate assignment.
Also removes the now-unused `import sys`.

Co-authored-by: Plane AI <noreply@plane.so>

---------

Co-authored-by: Plane AI <noreply@plane.so>
2026-06-23 17:59:19 +05:30
Manish Gupta
971c2aadb4 [WEB-7769] fix(security): scope EstimatePoint create/destroy to workspace and project (#9286)
GHSA-933r-rxg8-f3h2 — EstimatePointEndpoint.create trusted the
estimate_id URL parameter without verifying it belonged to the caller's
workspace and project. An authenticated user in project A could inject
estimate points into any other workspace's estimate by supplying a
foreign estimate_id.

Fix: added a workspace+project scoped Estimate ownership check before
EstimatePoint.objects.create().

GHSA-933r-rxg8-f3h2 (destroy) — old_estimate_point was fetched with
pk only (unscoped), allowing cross-tenant key disclosure and
manipulation during the key-rearrangement step.

Fix: scoped the old_estimate_point lookup to estimate_id + project_id +
workspace__slug; added 404 guard for missing/foreign points.

Note: BulkEstimatePointEndpoint.partial_update (GHSA-vm3j-5j49-gwrf)
was already correctly scoped at lines 116 and 125-130 — no change needed.

Co-authored-by: Plane AI <noreply@plane.so>
2026-06-23 17:52:41 +05:30
Manish Gupta
0d58adb69d [WEB-7774] fix(security): sanitize comment_html and intake description_html with nh3 (#9287)
GHSA-6qrq-f73q-r67j / GHSA-j9pv-f5wm-p4g2 — IssueCommentSerializer in
both app and api layers stored comment_html without sanitization. The app
layer had no validate() at all; the api layer only ran lxml structural
normalization which does not strip XSS payloads.

Fix: both serializers now call validate_html_content() (nh3-backed) in
their validate() methods, replacing the raw value with sanitized HTML.

GHSA-hh2r-3hwp-mvq3 — space/views/intake.py and api/views/intake.py
both used bare Issue.objects.create() with description_html taken
directly from request data, bypassing any serializer validation.

Fix: both paths now call validate_html_content() and pass the sanitized
value to Issue.objects.create(). Falls back to "<p></p>" if sanitizer
returns None (empty/invalid input).

The nh3 sanitizer (validate_html_content in content_validator.py) was
already present and used by IssueCreateSerializer — this change extends
coverage to the two remaining unsanitized comment and intake paths.

Co-authored-by: Plane AI <noreply@plane.so>
2026-06-23 17:52:31 +05:30
Manish Gupta
6220ba990b [WEB-7854] fix: prevent workspace invite token disclosure and invite hijack (#9297)
- Add WorkSpaceMemberInvitePublicSerializer that excludes token and
  invite_link; use it in WorkspaceJoinEndpoint.get() so an unauthenticated
  caller cannot retrieve the acceptance token from the GET endpoint
  (GHSA-86mg-259g-pwgg / GHSA-gf48-p6jp-cwc4).
- Require authentication and verify request.user.email matches the
  invited email before accepting a workspace invitation so an attacker
  who registers with the invited address cannot hijack the invite
  (GHSA-4vj8-p63v-8p24).

Co-authored-by: Plane AI <noreply@plane.so>
2026-06-23 17:47:16 +05:30
sriram veeraghanta
4a0746b45e fix: scope workspace user preference filter to current user (#9279)
* fix: scope workspace user preference filter to current user

Without user=request.user on the PATCH filter, the ORM could match
another user's preference record in the same workspace, causing
pin/unpin state to leak across users or silently fail to persist.

Fixes #9260

Signed-off-by: okxint <cashmein.eth@gmail.com>

* test: add regression coverage for workspace user preference scoping (#9260)

Adds contract tests for the sidebar preference PATCH endpoint:

- test_patch_only_updates_requesting_users_preference: in a multi-member
  workspace, a member's PATCH must update only their own preference row,
  never another member's. Fails against the pre-fix code (the unscoped
  .first() mutates the most-recently-created row regardless of user).
- test_patch_updates_own_preference: baseline that a member's PATCH
  persists to their own row.

Verified RED on the unpatched view and GREEN with the user=request.user
filter from #9261.

* fix(api): wrap long line to satisfy ruff E501 in user preference view

---------

Signed-off-by: okxint <cashmein.eth@gmail.com>
Co-authored-by: okxint <cashmein.eth@gmail.com>
2026-06-21 03:31:05 +05:30
okxint
64da8dc931 fix: Use APP_DOMAIN env var for bot user email (#9262)
* fix: Use APP_DOMAIN env var for bot user email instead of hardcoded plane.so

Signed-off-by: okxint <cashmein.eth@gmail.com>

* use settings.WEB_URL instead of APP_DOMAIN env var for bot email domain

---------

Signed-off-by: okxint <cashmein.eth@gmail.com>
2026-06-21 03:03:13 +05:30
sriram veeraghanta
7b0704d9cc fix(api): require at least one alphanumeric char in workspace name (#9278)
* fix(api): require at least one alphanumeric char in workspace name

Workspace name validation was enforced only on the frontend
(validateWorkspaceName), which gates the UI submit but is bypassable
via a direct API call. The backend WorkSpaceSerializer.validate_name
only rejected URLs, so a symbol-only name like "-_________-" could
still be saved via create or the rename (partial_update) path.

Add a Unicode-aware has_alphanumeric() helper and enforce it in both
the app and instance/license workspace serializers, mirroring the
frontend HAS_ALPHANUMERIC_REGEX (/[\p{L}\p{N}]/u) added in #9263.
International names (日本語, José, محمد) still pass since str.isalnum()
covers all scripts.

Adds unit tests covering symbol-only rejection and international
acceptance on both serializers.

Refs #9255

Signed-off-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>

* fix(api): reject URLs in instance workspace name for parity

Address CodeRabbit review on #9278: the instance/license
WorkspaceSerializer.validate_name rejected symbol-only names but, unlike
the app-level WorkSpaceSerializer, still accepted names containing URLs.
Add the same contains_url() guard (imported from plane.utils.url, not
content_validator) so both workspace-create paths validate identically.

Add unit tests asserting URL-containing names are rejected on both
serializers.

Signed-off-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>

---------

Signed-off-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
2026-06-20 17:36:37 +05:30
Manish Gupta
81d9873d7f [WEB-7727] fix(security): scope issue ID validation to workspace/project in bulk endpoints (#9269)
* fix(security): scope issue ID validation to workspace/project in bulk endpoints

Prevents cross-tenant IDOR by filtering incoming issue IDs through
workspace+project scope before bulk_create/bulk_update in:
- CycleIssueListCreateAPIEndpoint: validate new_issues against workspace+project (GHSA-22g9-9xfv-q3fr)
- SubIssuesEndpoint: validate sub_issue_ids against workspace (GHSA-38vj-gf85-7q5x)
- IssueRelationListCreateAPIEndpoint: validate issues against workspace (GHSA-8cvv-8jh5-g6mj)
- ModuleIssueListCreateAPIEndpoint: already scoped at line 673, no change needed (GHSA-x5c5-hmvm-94v9)

Co-authored-by: Plane AI <noreply@plane.so>

* fix(security): extend IDOR scope validation to app-layer endpoints

Same cross-tenant IDOR fix applied to the app/views/ counterparts
which are used by the web frontend (api/views/ covered in previous commit):
- app/views/cycle/issue.py: filter new_issues to workspace+project (GHSA-22g9-9xfv-q3fr)
- app/views/module/issue.py: filter issues to workspace+project before bulk_create (GHSA-x5c5-hmvm-94v9)
- app/views/issue/relation.py: filter issues to workspace before bulk_create (GHSA-8cvv-8jh5-g6mj)

Co-authored-by: Plane AI <noreply@plane.so>

* chore: remove advisory ID references from code comments

---------

Co-authored-by: Plane AI <noreply@plane.so>
Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
2026-06-20 17:07:42 +05:30
Manish Gupta
ad73ca300c [WEB-7730] fix(security): scope cascade deletes to workspace in BulkDeleteIssuesEndpoint (#9270)
* fix(security): scope cascade deletes to workspace in BulkDeleteIssuesEndpoint

CycleIssue and ModuleIssue cascade deletes used raw issue_ids from the
request instead of the already workspace+project scoped issues queryset,
allowing cross-workspace deletion of related records.

Fixes GHSA-6cw7-h92q-p9hg and GHSA-2rr4-rp7r-32p4.
GHSA-7q7r-mrr4-2wwx (sub-issue parent reassign) covered in WEB-7727.

Co-authored-by: Plane AI <noreply@plane.so>

* chore: remove advisory ID reference from code comment

---------

Co-authored-by: Plane AI <noreply@plane.so>
Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
2026-06-20 16:41:21 +05:30
Atul Tameshwari
00273d8feb refactor: update type imports for issue properties in issue modal context 2026-06-19 17:25:31 +05:30
Atul Tameshwari
1789e66b4f refactor: remove unused components and update import paths across the pages module 2026-06-18 14:20:32 +05:30
Atul Tameshwari
66e518134b refactor: remove unused mentions components and update import paths in the editor module 2026-06-18 13:36:59 +05:30
Atul Tameshwari
0df7221b9e refactor: remove unused issue components and update import paths across the issues module 2026-06-18 13:32:06 +05:30
Atul Tameshwari
c1736d6199 refactor: remove unused power-k components and update import paths in the command palette module 2026-06-17 19:44:10 +05:30
Atul Tameshwari
3a48eef483 refactor: update import paths for project components and remove unused files in the projects module 2026-06-17 18:00:02 +05:30
Atul Tameshwari
e364648ccf refactor: remove unused estimate and billing components, update import paths, and streamline workspace notification card structure 2026-06-17 17:41:02 +05:30
Atul Tameshwari
62bdc807a8 refactor: introduce new estimate, billing, and notification card components while updating import paths across various modules 2026-06-17 17:00:23 +05:30
Atul Tameshwari
bc3cd8a8bc refactor: remove unused sidebar components and update import paths in workspace notifications 2026-06-17 16:47:18 +05:30
Atul Tameshwari
0659fbacd2 refactor: remove unused components and clean up import paths across various modules 2026-06-17 16:36:37 +05:30
Atul Tameshwari
4f21a80e81 refactor: remove deprecated components and clean up import paths across various modules 2026-06-17 15:09:35 +05:30
Atul Tameshwari
bdc3b2a939 refactor: update import paths for workspace components and introduce new workspace-related files 2026-06-17 12:31:35 +05:30
Atul Tameshwari
217fe32dc5 refactor: introduce new members components and update import paths for workspace members functionality 2026-06-17 11:54:33 +05:30
Atul Tameshwari
0a2788a8dc refactor: introduce billing components and update import paths for billing-related files in core 2026-06-17 11:48:53 +05:30
Atul Tameshwari
96448da6f3 refactor: remove legacy helper components and introduce new access control and publish components in core 2026-06-17 11:05:34 +05:30
Atul Tameshwari
551df1e0e8 refactor: remove legacy gantt-chart components and introduce new core components for gantt-chart functionality 2026-06-17 10:54:07 +05:30
Atul Tameshwari
c6bb6b987b refactor: remove legacy estimate components and introduce new estimate-related files in core 2026-06-17 10:16:52 +05:30
Atul Tameshwari
328d08ba35 refactor: update import paths for workflow components and introduce new workflow-related files in core 2026-06-16 22:29:15 +05:30
Atul Tameshwari
28ab84fb7e refactor: remove legacy theme switcher component and update import paths in profile settings 2026-06-16 22:05:41 +05:30
Atul Tameshwari
ca3db9548a refactor: introduce onboarding tour components and update import paths for tour-related files 2026-06-16 21:24:31 +05:30
Atul Tameshwari
be637fc7fe refactor: remove legacy navigation components and update import paths for navigation items in core 2026-06-16 21:20:02 +05:30
Atul Tameshwari
7c19095e91 refactor: remove legacy license components and update import paths for PaidPlanUpgradeModal 2026-06-16 21:03:05 +05:30
Atul Tameshwari
e833d45310 refactor: remove legacy workspace-notifications index file and introduce new notification components in core 2026-06-16 20:25:54 +05:30
Atul Tameshwari
33228d6ac7 refactor: remove AdditionalFilterValueInput from legacy path and reintroduce it in core filter value input component 2026-06-16 19:09:26 +05:30
Atul Tameshwari
d43a0dd2d6 refactor: remove obsolete home index file, update import paths for relation options in issue detail components, and introduce new activity helper functions 2026-06-16 18:53:00 +05:30
Atul Tameshwari
479b4dbe56 refactor: add HomePageHeader and HomePeekOverviewsRoot components, update import paths in home and issues sections 2026-06-16 18:28:04 +05:30
Atul Tameshwari
351ffef89d refactor: add EpicModal component and update import paths in issue layouts 2026-06-16 18:21:38 +05:30
Atul Tameshwari
a82a6263f4 refactor: remove obsolete index file and introduce new version number and product updates components in core 2026-06-16 17:48:23 +05:30
Atul Tameshwari
b2ec91c989 refactor: add new desktop components and update import paths for sidebar functionality 2026-06-16 17:39:21 +05:30
Atul Tameshwari
58c71854fa refac: moved de-dupe directory to core 2026-06-16 17:24:42 +05:30
dependabot[bot]
2541a8c9cc chore(deps): bump cryptography (#9243)
Bumps the pip group with 1 update in the /apps/api/requirements directory: [cryptography](https://github.com/pyca/cryptography).


Updates `cryptography` from 46.0.7 to 48.0.1
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/46.0.7...48.0.1)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 48.0.1
  dependency-type: direct:production
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-16 17:14:42 +05:30
dependabot[bot]
7db4d8ec9a chore(deps): bump pyjwt (#9241)
Bumps the pip group with 1 update in the /apps/api/requirements directory: [pyjwt](https://github.com/jpadilla/pyjwt).


Updates `pyjwt` from 2.12.0 to 2.13.0
- [Release notes](https://github.com/jpadilla/pyjwt/releases)
- [Changelog](https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/jpadilla/pyjwt/compare/2.12.0...2.13.0)

---
updated-dependencies:
- dependency-name: pyjwt
  dependency-version: 2.13.0
  dependency-type: direct:production
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-16 17:03:44 +05:30
Atul Tameshwari
1fce8add7b refactor: remove obsolete cycle components and introduce new cycle-related components in core 2026-06-16 16:42:03 +05:30
Atul Tameshwari
613717a773 refactor: remove obsolete index file and add MaintenanceMessage and InboxSourcePill components 2026-06-16 15:22:29 +05:30
Atul Tameshwari
5a91581f31 refactor: update import paths for common components and introduce new ExtendedAppHeader, GlobalModals, and SubscriptionPill components 2026-06-16 15:12:15 +05:30