mirror of
https://github.com/penpot/penpot.git
synced 2026-10-28 21:40:34 +00:00
🐛 Reject restoring components of a linked library from plugins (#12611)
LibraryComponent.restore() did not check that the component belongs to the current file's library. Called on a deleted component of a connected shared library, it restored that component and saved the change to the library file, while remove(), annotation and duplicate() reject such handles with a validation error. restore() now rejects them the same way: "Can only restore components from the current file's library". Closes #12607
This commit is contained in:
parent
55ad7d1da8
commit
4fe73011ae
@ -917,6 +917,9 @@
|
||||
(not (r/check-permission plugin-id "library:write"))
|
||||
(u/not-valid plugin-id :restore "Plugin doesn't have 'library:write' permission")
|
||||
|
||||
(not= file-id (:current-file-id @st/state))
|
||||
(u/not-valid plugin-id :restore "Can only restore components from the current file's library")
|
||||
|
||||
(nil? component)
|
||||
(u/not-valid plugin-id :restore "Component does not exist")
|
||||
|
||||
|
||||
@ -55,13 +55,10 @@
|
||||
(cthf/apply-changes file changes)))
|
||||
|
||||
(t/deftest ^:async component-restore-preserves-the-users-view
|
||||
(doseq [scenario [:same-page :other-page :linked-library]]
|
||||
(doseq [scenario [:same-page :other-page]]
|
||||
(let [file (cond-> (file-with-deleted-component)
|
||||
(= scenario :other-page) (cthf/add-sample-page :other-page))
|
||||
store (if (= scenario :linked-library)
|
||||
(ths/setup-store (cthf/sample-file :local-file)
|
||||
{:renderer :svg :libraries [file]})
|
||||
(ths/setup-store file {:renderer :svg}))
|
||||
store (ths/setup-store file {:renderer :svg})
|
||||
view {:selected #{(thi/id :copy)}
|
||||
:zoom 2
|
||||
:vport {:x 100 :y 200 :width 800 :height 600}
|
||||
@ -108,6 +105,23 @@
|
||||
(t/is (empty? @events))
|
||||
(t/is (true? (get-in @store [:files (:id file) :data :components (thi/id :restorable) :deleted]))))))))
|
||||
|
||||
(t/deftest ^:async component-restore-rejects-linked-libraries
|
||||
(let [library (file-with-deleted-component)
|
||||
file (cthf/sample-file :consumer-file)
|
||||
store (ths/setup-store file {:renderer :svg :libraries [library]})
|
||||
before @store
|
||||
events (atom [])]
|
||||
(ptk/emit! store #(assoc-in % [:plugins :flags plugin-id :throw-validation-errors] true))
|
||||
(await
|
||||
(mock/with-mocks*
|
||||
{st/state store
|
||||
st/emit! (mock/stub (fn [& emitted] (swap! events into emitted)))}
|
||||
(let [component (library/lib-component-proxy plugin-id (:id library) (thi/id :restorable))]
|
||||
(t/is (thrown-with-msg? js/Error #"current file" (.restore component)))
|
||||
(await (async/settle))
|
||||
(t/is (empty? @events))
|
||||
(t/is (= (:files before) (:files @store))))))))
|
||||
|
||||
(t/deftest ^:async component-restore-rejects-a-missing-component
|
||||
(let [file (cthf/sample-file :restore-file)
|
||||
store (ths/setup-store file {:renderer :svg})]
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- **plugin-types:** Added `LibraryComponent.restore()` to restore a deleted component and its main instance without changing the current page, selection, zoom, or viewport. Requires `library:write` permission.
|
||||
- **plugin-types:** Added `LibraryComponent.restore()` to restore a deleted component and its main instance without changing the current page, selection, zoom, or viewport. Requires `library:write` permission and only applies to the current file's library.
|
||||
- **plugin-types:** Added `Shape.updateMain()`, `LibraryComponent.duplicate()`, writable component `annotation`, and `Library.deletedComponents`. Declared the existing `LibraryComponent.remove()` method.
|
||||
- **plugin-types:** Added `LibraryContext.tokensSource` to read or set the current file's token source to a connected library, or restore local tokens.
|
||||
- **plugin-types:** Added `paddingType` (`'simple' | 'multiple'`) to flex and grid layouts and `marginType` (`'simple' | 'multiple'`) to layout children, exposing whether the four padding/margin sides are mirrored or honoured independently.
|
||||
|
||||
3
plugins/libs/plugin-types/index.d.ts
vendored
3
plugins/libs/plugin-types/index.d.ts
vendored
@ -2791,7 +2791,8 @@ export interface LibraryComponent extends LibraryElement {
|
||||
remove(): void;
|
||||
|
||||
/**
|
||||
* Restores this component if it has been deleted, including its main instance.
|
||||
* Restores this component if it has been deleted, including its main instance,
|
||||
* in the current file's library.
|
||||
* Leaves the current page, selection, zoom, and viewport unchanged.
|
||||
* Requires `library:write` permission. Does nothing if already restored.
|
||||
*
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user