Skip to content

Commit 5d696cd

Browse files
up doc
1 parent 61ab5c6 commit 5d696cd

File tree

5 files changed

+330
-323
lines changed

5 files changed

+330
-323
lines changed

content/extensions/filtering.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Filtering UI extensions
1+
# Filter and display UI extensions
22

33
You may want to create UI extensions that are only available to certain user groups or for specific products. This can be achieved by filtering UI extensions based on user groups and product selection.
44

@@ -13,5 +13,9 @@ You can filter the products that can be selected by an UI extension by using the
1313

1414
[![ui-extension-product-selection.png](../img/extensions/ui-extensions/ui-extension-product-selection.png)](../img/extensions/ui-extensions/ui-extension-product-selection.png)
1515

16+
### Order UI extensions
17+
18+
In addition to the filtering capacity, you can order the UI extension in the UI using the `weight` field on the creation/update form. This will determine the order in which extensions are displayed in the **header** and **tab** positions.
19+
1620
::: panel-link FAQ [Next](/extensions/faq.html)
1721
:::

content/extensions/getting-started.md

Lines changed: 0 additions & 320 deletions
Original file line numberDiff line numberDiff line change
@@ -173,326 +173,6 @@ To delete a UI extension, you must have a valid PIM API token and the UUID of th
173173
--header "Authorization: Bearer $PIM_API_TOKEN"
174174
```
175175

176-
## Types
177-
178-
UI extensions are categorized by type, which determines their capabilities. Select the type that best suits your requirements:
179-
+ action
180-
+ iframe
181-
+ link
182-
183-
### Link
184-
A **link** UI extension is crafted to open your external content in a new tab.
185-
186-
To create a `link` UI extension, mandatory fields are `name`, `position`, `type`, and `configuration`. Inside `configuration`, mandatory options are `default_label` and `url`.
187-
188-
#### Url Placeholders
189-
The Url of a **link** UI extension can be based on the context thanks to a placeholder pattern.
190-
191-
For example, you can configure a UI extension with the following url `https://www.google.com/search?q=%name%&tbm=shop&gl=us`. When the link is clicked, `%name%` will be replaced with the context attribute values.
192-
193-
Valid placeholders attributes are:
194-
- `uuid` (for products), `code` (for product models) and other attribute of type `identifier`
195-
- all `text` attributes. Links will use the value related to the current locale or channel.
196-
197-
You can add a placeholder anywhere in your url as soon as they're surrounded by `%` symbol.
198-
199-
Examples:
200-
- `https://www.google.com/search?q=%name%`
201-
- `https://yourwebsite.com/%sku%`
202-
- `%base_url%/sub-url`
203-
204-
::: warning
205-
If the URL begins with a placeholder, we won't verify its validity. The link might not work when used.
206-
:::
207-
208-
### Iframe
209-
An **iframe** UI extension allows to open your external content inside the PIM thanks to an iframe.
210-
211-
An iframe (inline frame) is an HTML element that allows you to embed another HTML document within the current document. It is commonly used to display content from another source, such as a webpage, video, or interactive content, without leaving the current page.
212-
213-
For more detailed information, you can refer to the [Mozilla Developer Network (MDN) documentation on iframes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe).
214-
215-
To configure an `iframe` UI extension, mandatory fields are `name`, `position`, `type`, and `configuration`. Inside `configuration`, mandatory options are `default_label`, `secret` and `url`.
216-
217-
::: warning
218-
**Important security notice**
219-
220-
For sensitive data, we recommend implementing [security measures](#ensuring-security-of-embedded-iframes) to protect your information.
221-
:::
222-
223-
#### Default query parameters
224-
To help identify the **iframe** caller (insecure) and context, several parameters are sent by default as SearchParameters in the GET query.
225-
226-
For example, when `url` is `https://customerwebsite.com/iframe/`, the called URL is `https://customerwebite.com/iframe/?position=pim.product.tab&user[username]=julia`
227-
228-
For all positions, parameters relative to the connected user and the extension position are sent:
229-
- `user[uuid]`
230-
- `user[id]`
231-
- `user[username]`
232-
- `user[email]`
233-
- `user[ui_locale]`
234-
- `user[catalog_locale]` except for `pim.product-grid.action-bar`
235-
- `user[catalog_scope]` except for `pim.product-grid.action-bar`
236-
- `position`
237-
238-
For `pim.product.tab` position, these parameters are sent:
239-
- `product[uuid]`
240-
- `product[identifier]`
241-
242-
For `pim.product-model.tab` and `pim.sub-product-model.header` position, this parameter is sent:
243-
- `product[code]`
244-
245-
For `pim.category.tab` position, this parameter is sent:
246-
- `category[code]`
247-
248-
#### Get PIM data from the iframe
249-
250-
To be able to communicate the products or product models selection (from position `pim.product-grid.action-bar`) to the iframe, we use the [PostMessage](https://developer.mozilla.org/docs/Web/API/Window/postMessage) protocol.
251-
252-
After the iframe is loaded, the PIM send an *event* which is a normalized message [MessageEvent](https://developer.mozilla.org/docs/Web/API/MessageEvent) with a field `data` containing our information.
253-
254-
This field contains :
255-
- A `data` object with :
256-
- A `productUuids` field which is an array of string representing the UUIDs of selected products
257-
- A `productModelCodes` field which is an array of string representing the codes of selected product models and sub models
258-
- A `context` object containing the configured `locale` and `channel`.
259-
- A `user` object containing the `uuid`, `username` and `groups` of the connected user.
260-
261-
Example :
262-
```json
263-
{
264-
"data": {
265-
"productUuids": [
266-
"63139bf3-a7f7-4eaa-ba5e-6ffc8a2f14e9",
267-
"6fa3bd36-6b5a-4e80-afcd-c224fdf6f3ea",
268-
"78f38e4a-8d25-41e1-8e09-42a9c246689a"
269-
],
270-
"productModelCodes": []
271-
},
272-
"context": {
273-
"locale": "en_US",
274-
"channel": "ecommerce"
275-
},
276-
"user": {
277-
"uuid": "4ebad9a4-7728-4d90-9db0-9e5a5c6a4d45",
278-
"username": "admin",
279-
"groups": [
280-
"IT support",
281-
"All"
282-
]
283-
}
284-
}
285-
```
286-
287-
For a *classical* project with HTML and JavaScript code, you can include this kind of code to catch those events :
288-
289-
```html
290-
<script>
291-
window.addEventListener('message', (event) => {
292-
console.log(event)
293-
});
294-
</script>
295-
```
296-
297-
For more *modern* technologies like ReactJS, the iframe could be loaded before components. To solve this problem we added the possibility to ask for the data. To do this, just send a PostMessage with an object containing the property `type: 'request_context'`.
298-
299-
Example :
300-
```js
301-
window.parent.postMessage(
302-
{
303-
type: 'request_context'
304-
},
305-
"*"
306-
);
307-
```
308-
After receiving this *event*, the PIM will send a PostMessage *event*, similar to the one sent after the iframe loading.
309-
310-
#### Product and product model context change
311-
312-
The **PIM context** is propagated within the iframe when it changes using **postmessage**. This only applies to the product and product model positions: **pim.product-model.header**, **pim.sub-product-model.header** and **pim.product.header**.
313-
314-
The message contains :
315-
- A `context` object containing the selected `locale` and `channel`.
316-
- A `user` object containing the `uuid`, `username` and `groups` of the connected user.
317-
318-
Example :
319-
```json
320-
{
321-
"context": {
322-
"locale": "en_US",
323-
"channel": "ecommerce"
324-
},
325-
"user": {
326-
"uuid": "c71228d3-695c-4ded-8f3d-b3ed881a1f59",
327-
"username": "admin",
328-
"groups": [
329-
"IT support",
330-
"All"
331-
]
332-
}
333-
}
334-
```
335-
336-
#### Ensuring security of embedded iframes
337-
338-
To help ensuring the security of iframes we recommand using these two solutions:
339-
340-
* Properly configure [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) headers to control the sources from which content can be loaded.
341-
342-
::: warning
343-
Please note that if these headers are misconfigured, iframe functionality may not work as intended.
344-
:::
345-
346-
* Use your extension secret and ```postMessage``` to get and verify the signature of a JW token. This secret will be used to generate a JWT token when the iframe is loaded by the PIM system.
347-
348-
**Get a JW Token via ```postMessage```**
349-
350-
First, from your iframe, you must request for the JWT by doing a PostMessage with a payload containing ```type: 'request_jwt'```
351-
352-
Example :
353-
```js
354-
window.parent.postMessage(
355-
{
356-
type: 'request_jwt'
357-
},
358-
"*"
359-
);
360-
```
361-
362-
the PIM will then answer with a postMessage containing the JWT token. The message will be structured as follows:
363-
364-
```json
365-
{
366-
"type": "JWT_TOKEN",
367-
"token": "jwt_value"
368-
}
369-
```
370-
371-
* The JWT token in the token field is generated using SHA256 encryption based on the secret you provided.
372-
373-
For more information on how JWT tokens are structured and used, you can refer to the associated [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519).
374-
375-
**JWT Token Structure**
376-
377-
The JWT token consists of three main parts: the header, the body (payload), and the signature.
378-
379-
*Header*
380-
381-
* The header typically contains information about the token type and the signing algorithm. In this case, it will look like:
382-
383-
```json
384-
{
385-
"typ": "JWT",
386-
"alg": "HS256"
387-
}
388-
```
389-
390-
*Payload*
391-
392-
* The payload contains the claims. The JWT token’s will look like this:
393-
394-
```json
395-
{
396-
"jti": "c1b6b9f1-8486-4f9e-9f96-8d1b40fccb65",
397-
"iat": 1743410036.116152,
398-
"exp": 1743413636.116162,
399-
"userId": "1",
400-
"userUuid": "557ed4c9-e155-4f4c-802d-4d90bca37d45"
401-
}
402-
```
403-
404-
* ```jti``` The unique identifier for the token.
405-
* ```iat``` The issued at time.
406-
* ```exp``` The expiration time of the token.
407-
* ```userId``` The PIM user legacy identifier (in this case, ```1```).
408-
* ```userUuid``` The PIM user Uuid.
409-
410-
*A signature*
411-
412-
* The signature is used to verify that the token is valid and has not been tampered with. It is generated by combining the encoded header and payload, and then signing them with the secret key. The resulting signature might look like:
413-
```9WBB7ayP8UnFrOlMrI9NzTj3kxaiXOWJzElyacEKt48```
414-
415-
**Verifying the Signature**
416-
417-
To ensure that the JWT token was issued by Akeneo, you can verify the signature by re-encoding the header and payload and then signing them using the same secret key. This will allow you to confirm that the token is valid and has not been altered.
418-
419-
### Action
420-
An **action** UI extension is designed to perform external tasks in the background. Please note the following key points regarding its functionality:
421-
422-
+ **Single execution**: An action cannot be executed multiple times simultaneously. This ensures that tasks are processed in a controlled manner.
423-
+ **Menu deactivation**: During the execution of an action, the associated menu will be deactivated to prevent further interactions until the task is complete.
424-
+ **Notification on completion**: A notification will appear once the external server responds to the request, keeping users informed of the task's status.
425-
+ **Timeout**: The PIM HTTP client that communicates with the destination is configured with a timeout of 5 seconds.
426-
+ **POST HTTP method**: The request being sent to the destination is a POST request.
427-
+ **Signature**: It's possible to configure a `secret` to sign the body of the POST request sent to the destination (<a href='https://wikipedia.org/wiki/SHA-2'>SHA-512</a> protocol).
428-
429-
Here is a diagram illustrating the workflow:
430-
[![action-extension-schema.png](../img/extensions/ui-extensions/action-extension-schema.png)](../img/extensions/ui-extensions/action-extension-schema.png)
431-
432-
Data sent within the POST body, formatted in JSON, contains :
433-
- A `data` object with different fields depending on the [position](#position).
434-
- A `context` object containing the configured `locale` and `channel`.
435-
- A `user` object containing the `uuid`, `username` and `groups` of the connected user.
436-
- A `timestamp` that can be used with a [secret](#secret) to help you to protect your server against [replay attacks](https://en.wikipedia.org/wiki/Replay_attack).
437-
438-
From a position `pim.product.header`, the `data` object contains :
439-
- A `productUuid` string field
440-
441-
From a position `pim.product-model.header`, the `data` object contains :
442-
- A `productModelCode` string field representing the root model code.
443-
444-
From a position `pim.sub-product-model.header`, the `data` object contains :
445-
- A `productModelCode` string field representing the sub model code.
446-
447-
From a position `pim.product-grid.action-bar`, the `data` object contains :
448-
- A `productUuids` field which is an array of string representing the UUIDs of selected products
449-
- A `productModelCodes` field which is an array of string representing the codes of selected product models and sub models
450-
451-
Examples :
452-
453-
```json
454-
{
455-
"data": {
456-
"productUuid": "ecfddba2-59bf-4d35-bd07-8ceeefde51fd"
457-
},
458-
"context": {
459-
"locale": "en_US",
460-
"channel": "ecommerce"
461-
},
462-
"user": {
463-
"uuid": "e05cc457-b8ac-43b1-baa7-c4c112091ad8",
464-
"username": "julia",
465-
"groups": [
466-
"Manager",
467-
"All"
468-
]
469-
},
470-
"timestamp": 1739948408
471-
}
472-
```
473-
474-
```json
475-
{
476-
"data": {
477-
"productUuids": [],
478-
"productModelCodes": ["armor", "apollon"]
479-
},
480-
"context": {
481-
"locale": "en_US",
482-
"channel": "ecommerce"
483-
},
484-
"user": {
485-
"uuid": "e05cc457-b8ac-43b1-baa7-c4c112091ad8",
486-
"username": "julia",
487-
"groups": [
488-
"Manager",
489-
"All"
490-
]
491-
},
492-
"timestamp": 1739948408
493-
}
494-
```
495-
496176
## Administration of UI extensions
497177
For a functional overview of the administration panel and permissions, see our [Help Center](https://help.akeneo.com/extensions/ui-extentions).
498178

0 commit comments

Comments
 (0)