3207 Commits

Author SHA1 Message Date
Edwin Rivera
2579527e64
🎉 Add get-file-stats RPC command (#9074)
* 🎉 Add get-file-stats RPC command

Introduce a new lightweight RPC query that returns aggregate statistics
for a single file: page count, shape counts by type, component/color/
typography counts, and inbound and outbound library reference counts.
Mirrors the existing get-file-summary permission and decoding pattern.

Useful for plugin authors enforcing per-file budgets, the
@penpot/library npm SDK, and future admin dashboards. Purely additive
— no migrations, no UI, no breaking changes.

Signed-off-by: edwin-rivera-dev <bytelogic772@gmail.com>

* 🐛 Bind *load-fn* around file data walk in get-file-stats

The binding previously wrapped only  — a plain key
lookup that does not realize any pointers — so by the time
 walked  and accessed  on
each page,  was unbound and every PointerMap
dereference threw , failing the three new  tests.

Move  inside the  form so the walk runs
with  available, matching the existing pattern used in
.

Signed-off-by: Edwin Rivera <bytelogic772@gmail.com>

---------

Signed-off-by: edwin-rivera-dev <bytelogic772@gmail.com>
Signed-off-by: Edwin Rivera <bytelogic772@gmail.com>
2026-04-22 12:49:39 +02:00
María Valderrama
b67394199b
Add the ability to upload organization profile image
*  Upload org logo

* 📎 Code review

* 📎 Code review 2

* 📎 Code review 3
2026-04-22 09:37:09 +02:00
Pablo Alba
ad974f4047 💄 Unify naming on nitrate-api 2026-04-22 09:31:09 +02:00
Andrey Antukh
d8340d765a Merge remote-tracking branch 'origin/staging' into develop 2026-04-21 20:28:38 +02:00
Andrey Antukh
6eccffb8bb
🐛 Fix incorrect handlig of version restore operation (#9041)
- Add session ID tracking to RPC layer (backend and frontend)
- Send session ID header with RPC requests for request correlation
- Rename file-restore to file-restored for consistency
- Extract initialize-file function from initialize-workspace flow
- Improve file restoration initialization with wait-for-persistence
- Extract initialize-version event handler for version restoration
- Fix viewport key generation with file version numbers for proper re-renders
- Update layout item schema and constraints to use internal sizing state
- Add v-sizing state retrieval in layout-size-constraints component
- Refactor file-change notifications stream handling with rx/map
- Fix team-id lookup in restore-version-from-plugins

Improves request traceability across frontend/backend sessions and streamlines
the workspace initialization flow for file restoration scenarios.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-21 19:19:51 +02:00
moorsecopers99
95b2d7b083
🐛 Add ability to delete uploaded profile avatar (#9068)
Fixes #9067. Adds a delete button that appears on hover over an
uploaded profile photo; clicking it opens a confirm modal and, on
accept, clears the stored photo so the generated fallback avatar is
shown again. A new :delete-profile-photo RPC schedules the old
storage object for garbage collection and sets photo-id to null.

Signed-off-by: moorsecopers99 <patellscott18@gmail.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-21 19:19:30 +02:00
Pablo Alba
cd320c0cd6 On profile deletion, remove the user from nitrate too 2026-04-21 15:44:37 +02:00
Alejandro Alonso
0d17debde7 Merge remote-tracking branch 'origin/staging' into develop 2026-04-21 08:24:29 +02:00
Pablo Alba
73b55ee47e Add nitrate api method get-remove-from-org-summary 2026-04-20 11:18:07 +02:00
Pablo Alba
ae66317d6c Add nitrate api to remove user from org 2026-04-20 11:18:07 +02:00
Pablo Alba
b2c9e08d42 🐛 Fix bad check on leave nitrate org 2026-04-20 11:18:07 +02:00
Pablo Alba
a206d57443 Add team to a nitrate organization 2026-04-17 11:38:52 +02:00
Andrey Antukh
6fa440cf92 🎉 Add chunked upload API for large media and binary files
Introduce a purpose-agnostic three-step session-based upload API that
allows uploading large binary blobs (media files and .penpot imports)
without hitting multipart size limits.

Backend:
- Migration 0147: new `upload_session` table (profile_id, total_chunks,
  created_at) with indexes on profile_id and created_at.
- Three new RPC commands in media.clj:
    * `create-upload-session`  – allocates a session row; enforces
      `upload-sessions-per-profile` and `upload-chunks-per-session`
      quota limits (configurable in config.clj, defaults 5 / 20).
    * `upload-chunk`           – stores each slice as a storage object;
      validates chunk index bounds and profile ownership.
    * `assemble-file-media-object` – reassembles chunks via the shared
      `assemble-chunks!` helper and creates the final media object.
- `assemble-chunks!` is a public helper in media.clj shared by both
  `assemble-file-media-object` and `import-binfile`.
- `import-binfile` (binfile.clj): accepts an optional `upload-id` param;
  when provided, materialises the temp file from chunks instead of
  expecting an inline multipart body, removing the 200 MiB body limit
  on .penpot imports.  Schema updated with an `:and` validator requiring
  either `:file` or `:upload-id`.
- quotes.clj: new `upload-sessions-per-profile` quota check.
- Background GC task (`tasks/upload_session_gc.clj`): deletes stalled
  (never-completed) sessions older than 1 hour; scheduled daily at
  midnight via the cron system in main.clj.
- backend/AGENTS.md: document the background-task wiring pattern.

Frontend:
- New `app.main.data.uploads` namespace: generic `upload-blob-chunked`
  helper drives steps 1–2 (create session + upload all chunks with a
  concurrency cap of 2) and emits `{:session-id uuid}` for callers.
- `config.cljs`: expose `upload-chunk-size` (default 25 MiB, overridable
  via `penpotUploadChunkSize` global).
- `workspace/media.cljs`: blobs ≥ chunk-size go through the chunked path
  (`upload-blob-chunked` → `assemble-file-media-object`); smaller blobs
  use the existing direct `upload-file-media-object` path.
  `handle-media-error` simplified; `on-error` callback removed.
- `worker/import.cljs`: new `import-blob-via-upload` helper replaces the
  inline multipart approach for both binfile-v1 and binfile-v3 imports.
- `repo.cljs`: `:upload-chunk` derived as a `::multipart-upload`;
  `form-data?` removed from `import-binfile` (JSON params only).

Tests:
- Backend (rpc_media_test.clj): happy path, idempotency, permission
  isolation, invalid media type, missing chunks, session-not-found,
  chunk-index out-of-range, and quota-limit scenarios.
- Frontend (uploads_test.cljs): session creation and chunk-count
  correctness for `upload-blob-chunked`.
- Frontend (workspace_media_test.cljs): direct-upload path for small
  blobs, chunked path for large blobs, and chunk-count correctness for
  `process-blobs`.
- `helpers/http.cljs`: shared fetch-mock helpers (`install-fetch-mock!`,
  `make-json-response`, `make-transit-response`, `url->cmd`).

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-16 19:43:57 +02:00
Andrey Antukh
974beca12d Add 2h min-age threshold to storage/gc_touched task
Skip storage objects touched less than 2 hours ago, matching the pattern
used by upload-session-gc. Update all affected tests to advance the clock
past the threshold using ct/*clock* bindings.
2026-04-16 19:43:57 +02:00
Pablo Alba
39f4c13493
Add nitrate remove team from org 2026-04-16 11:46:05 +02:00
Pablo Alba
65a0fcb15b
🐛 Fix on nitrate leave org default org team must be deleted if empty 2026-04-16 11:45:37 +02:00
Pablo Alba
ac472c615a
🐛 Fix nitrate invitations org ux review 2026-04-16 11:18:11 +02:00
aliworksx08
81061013b1
Add openid-attr support and dot notation for OIDC attribute (#8946)
*  Add openid-attr support and dot notation for OIDC attribute paths

* ♻️ Simplify OIDC: add dot-notation for attr paths and retain sub claim

* ♻️ Fix OIDC: fix

* 🐛 Fix OIDC nested attr lookup for dot notation

* ♻️ Remove unused OIDC openid-attr support

---------

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-04-16 11:12:37 +02:00
Andrey Antukh
b5922d32ca Merge remote-tracking branch 'origin/main' into staging 2026-04-16 10:59:36 +02:00
Andrey Antukh
de27ea904d
Add minor adjustments to the auth events (#9027) 2026-04-16 09:59:45 +02:00
Andrey Antukh
a7e362dbfe 📎 Add commented helpers on backend _env for testing nexus 2026-04-15 18:03:11 +02:00
Andrey Antukh
f8f7a0828e Add missing indexes on audit_log table 2026-04-15 18:02:13 +02:00
Juanfran
f5591ed22e 🐛 Forward email when adding user to Nitrate organization 2026-04-15 13:28:39 +02:00
Juanfran
de577a803c 🎉 Add get-org-member-team-counts endpoint to Nitrate API 2026-04-15 08:50:13 +02:00
Pablo Alba
5c761125f3 Add invite-to-org to Nitrate API 2026-04-13 11:49:01 +02:00
Marina López
707cc53ca4
Revert Add can use trial prop in nitrate profile (#8954) 2026-04-13 11:41:32 +02:00
Pablo Alba
d65f3b5396 Add nitrate api endpoints to get an user profile 2026-04-09 12:10:06 +02:00
Pablo Alba
fe2023dde5 Add nitrate api endpoints to get an user profile 2026-04-09 12:10:06 +02:00
Marina López
1c68810521 Add can use trial prop in nitrate profile 2026-04-09 11:15:21 +02:00
Juanfran
e51e0c7933 Add theme field to nitrate authenticate response 2026-04-09 09:19:36 +02:00
Andrey Antukh
5937a8b0fc Merge remote-tracking branch 'origin/staging' into develop 2026-04-09 09:13:02 +02:00
Andrey Antukh
11fbd4cb21 Merge remote-tracking branch 'origin/main' into staging 2026-04-09 09:12:23 +02:00
Andrey Antukh
c8675c5b7e
♻️ Normalize newsletter-updates checbox on different register flows (#8839)
*  Add newsletter opt-in checkbox to registration validation form

Add accept-newsletter-updates support through the full registration
token flow. The newsletter checkbox is now available on the
registration validation form, allowing users to opt-in during the
email verification step.

Backend changes:
- Refactor prepare-register to consolidate UTM params and newsletter
  preference into props at token creation time
- Add accept-newsletter-updates to prepare-register-profile and
  register-profile schemas
- Handle newsletter-updates in register-profile by updating token
  claims props on second step

Frontend changes:
- Add newsletter-options component to register-validate-form
- Add accept-newsletter-updates to validation schema
- Fix subscription finalize/error handling in register form

Signed-off-by: Andrey Antukh <niwi@niwi.nz>

* ♻️ Refactor auth register components to modern style

Migrate all components in app.main.ui.auth.register and
app.main.ui.auth.login/demo-warning to use the modern * suffix
convention, removing deprecated ::mf/props :obj metadata and
updating all invocations from [:& name] to [:> name*] syntax.

Components updated:
- terms-and-privacy -> terms-and-privacy*
- register-form -> register-form*
- register-methods -> register-methods*
- register-page -> register-page*
- register-success-page -> register-success-page*
- terms-register -> terms-register*
- register-validate-form -> register-validate-form*
- register-validate-page -> register-validate-page*
- demo-warning -> demo-warning*

Also remove unused old context-notification import in login.cljs.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>

* 🔥 Remove unused onboarding-newsletter component

The newsletter opt-in is now handled directly in the registration
form via the newsletter-options* component, making the standalone
onboarding-newsletter modal obsolete.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>

* 🐛 Fix register test for UTM params to use prepare-register step

UTM params are now extracted and stored in token props during the
prepare-register step, not at register-profile time. Move utm_campaign
and mtm_campaign from the register-profile call to the
prepare-register-profile call in the test.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>

---------

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-08 17:00:52 +02:00
Andrey Antukh
0cc5f7c63e Merge remote-tracking branch 'origin/staging' into develop 2026-04-07 19:28:23 +02:00
Andrey Antukh
a27ef26279 Merge remote-tracking branch 'origin/main' into staging 2026-04-07 19:23:37 +02:00
Pablo Alba
3c639f41c4
Add option to leave a nitrate organization 2026-04-07 11:26:57 +02:00
Andrey Antukh
81b1b253f1
Add unique email domains to telemetry report (#8819)
Extend the telemetry payload with a sorted list of unique email domains
extracted from all registered profile email addresses. The new
:email-domains field is populated via a single SQL query using
split_part and DISTINCT, and is included in the stats sent when
telemetry is enabled.

Also update the tasks-telemetry-test to assert the new field is present
and contains the expected domain values.
2026-04-01 11:49:50 +02:00
Andrey Antukh
650762556f Merge remote-tracking branch 'origin/staging' into develop 2026-04-01 11:30:39 +02:00
Andrey Antukh
103af0e31a 📎 Fix inconsistencies on error report context data 2026-04-01 10:26:04 +02:00
Andrey Antukh
c097c4a6da Merge remote-tracking branch 'origin/staging' into develop 2026-04-01 09:26:05 +02:00
Andrey Antukh
d6dc0fe1a7
🐛 Fix raw file data download on dbg pannel (#8847) 2026-03-31 14:36:43 +02:00
Andrey Antukh
87bb1b8e74 Merge remote-tracking branch 'origin/staging' into develop 2026-03-30 12:29:43 +02:00
Andrey Antukh
264cd0aaac Merge remote-tracking branch 'origin/main' into staging 2026-03-30 12:29:07 +02:00
Pablo Alba
06aec4b3a3
Add is-default to nitrate summary (#8814) 2026-03-30 09:39:35 +02:00
Pablo Alba
51b9023640
Show nitrate org name on invitation to join team email (#8802) 2026-03-26 17:25:30 +01:00
Pablo Alba
4b4b99a949
Add response to nitrate request when nitrate is down (#8722) 2026-03-26 17:25:07 +01:00
Andrey Antukh
0dfa62a5b6
🐛 Improve error reporting on request parsing failures (#8805)
Include request URI and status in frontend handle-response error data,
and add request path/context to backend IOException handler logs and
response body. Previously these errors had no identifying information
about which endpoint or request caused the failure.
2026-03-26 15:42:49 +01:00
Pablo Alba
1af2521f64 Add create default team org for nitrate on adding an user to a team 2026-03-26 13:17:05 +01:00
Marina López
6fa0c5ceaa Add organization avatar 2026-03-26 10:54:55 +01:00
Andrey Antukh
d4bc1d37f2 Merge remote-tracking branch 'origin/staging' into develop 2026-03-24 18:08:23 +01:00