Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IBX-7275: Exposed base admin UI configuration in REST API #1027

Merged

Conversation

ciastektk
Copy link
Contributor

@ciastektk ciastektk commented Dec 4, 2023

Question Answer
Tickets https://issues.ibexa.co/browse/IBX-7275
Bug fix? no
New feature? yes
BC breaks? no
Tests pass? yes
Doc needed? yes
License GPL-2.0
Requires ibexa/rest#79

Endpoint

[GET] /api/ibexa/v2/application-config

This PR adds dedicated endpoint to get base admin ui config in REST API. The same configuration is stored in window.ibexa.adminUIConfig.

Response

JSON

{
    "ApplicationConfig": {
        "_media-type": "application/vnd.ibexa.api.ApplicationConfig+json",
        "multiFileUpload": {
            "locationMappings": [],
            "defaultMappings": [
                {
                    "mimeTypes": [],
                    "contentTypeIdentifier": "image",
                    "contentFieldIdentifier": "asset",
                    "nameFieldIdentifier": "title"
                }
            ],
            "fallbackContentType": {
                "contentTypeIdentifier": "image",
                "contentFieldIdentifier": "asset",
                "nameFieldIdentifier": "title"
            },
            "maxFileSize": 5242880
        },
        "sortFieldMappings": {
            "PATH": "LocationPath",
            "PUBLISHED": "DatePublished",
            "MODIFIED": "DateModified",
            "SECTION": "SectionIdentifier",
            "DEPTH": "LocationDepth",
            "PRIORITY": "LocationPriority",
            "NAME": "ContentName",
            "NODE_ID": "LocationId",
            "CONTENTOBJECT_ID": "ContentId"
        },
        "sortOrderMappings": {
            "ASC": "ascending",
            "DESC": "descending"
        },
        "imageVariations": {
            "original": null,
            "reference": {
                "reference": null,
                "filters": {
                    "geometry/scaledownonly": [
                        600,
                        600
                    ]
                }
            },
            "small": {
                "reference": "reference",
                "filters": {
                    "geometry/scaledownonly": [
                        100,
                        100
                    ]
                }
            },
            "tiny": {
                "reference": "reference",
                "filters": {
                    "geometry/scaledownonly": [
                        30,
                        30
                    ]
                }
            },
            "medium": {
                "reference": "reference",
                "filters": {
                    "geometry/scaledownonly": [
                        200,
                        200
                    ]
                }
            },
            "large": {
                "reference": "reference",
                "filters": {
                    "geometry/scaledownonly": [
                        300,
                        300
                    ]
                }
            },
            "ezplatform_admin_ui_profile_picture_user_menu": {
                "reference": "reference",
                "filters": {
                    "geometry/scaledownonly": [
                        30,
                        30
                    ],
                    "geometry/crop": [
                        30,
                        30,
                        0,
                        0
                    ]
                },
                "post_processors": []
            }
        },
        "contentEditFormTemplates": [],
        "user": {
            "user": null,
            "profile_picture_field": null
        },
        "languages": {
            "mappings": {
                "eng-GB": {
                    "name": "English (United Kingdom)",
                    "id": 2,
                    "languageCode": "eng-GB",
                    "enabled": true
                }
            },
            "priority": [
                "eng-GB"
            ]
        },
        "contentTypes": {
            "Content": [
                {
                    "id": 1,
                    "identifier": "folder",
                    "name": "Folder",
                    "isContainer": true,
                    "thumbnail": "/bundles/ibexaadminui/img/ibexa-icons.svg#folder",
                    "href": "/api/ibexa/v2/content/types/1"
                }
            ],
            "Users": [
                {
                    "id": 4,
                    "identifier": "user",
                    "name": "User",
                    "isContainer": false,
                    "thumbnail": "/bundles/ibexaadminui/img/ibexa-icons.svg#user",
                    "href": "/api/ibexa/v2/content/types/4"
                },
                {
                    "id": 3,
                    "identifier": "user_group",
                    "name": "User group",
                    "isContainer": true,
                    "thumbnail": "/bundles/ibexaadminui/img/ibexa-icons.svg#user_group",
                    "href": "/api/ibexa/v2/content/types/3"
                }
            ],
            "Media": [
                {
                    "id": 13,
                    "identifier": "image",
                    "name": "Image",
                    "isContainer": false,
                    "thumbnail": "/bundles/ibexaadminui/img/ibexa-icons.svg#image",
                    "href": "/api/ibexa/v2/content/types/13"
                }
            ]
        },
        "universalDiscoveryWidget": {
            "startingLocationId": 1
        },
        "subItems": {
            "limit": 10
        },
        "imageAssetMapping": {
            "contentTypeIdentifier": "image",
            "contentFieldIdentifier": "image",
            "nameFieldIdentifier": "name",
            "parentLocationId": 51
        },
        "notifications": {
            "error": {
                "timeout": 0
            },
            "warning": {
                "timeout": 0
            },
            "info": {
                "timeout": 0
            },
            "success": {
                "timeout": 5000
            }
        },
        "timezone": "UTC",
        "dateFormat": {
            "fullDateTime": "LLLL dd, yyyy HH:mm",
            "fullDate": "LLLL dd, yyyy",
            "fullTime": "HH:mm",
            "shortDateTime": "dd/MM/yyyy HH:mm",
            "shortDate": "dd/MM/yyyy",
            "shortTime": "HH:mm"
        },
        "autosave": {
            "enabled": false,
            "interval": 60000
        },
        "userContentTypes": [
            "user"
        ],
        "sections": [],
        "locations": {
            "media": 43,
            "contentStructure": 2,
            "users": 5
        },
        "iconPaths": {
            "iconSets": {
                "public_icons": "/bundles/ibexaadminui/img/ibexa-icons.svg",
                "streamlineicons": "/bundles/ibexaicons/img/all-icons.svg"
            },
            "defaultIconSet": "streamlineicons"
        },
        "backOfficeLanguage": "en",
        "backOfficePath": "/",
        "suggestions": {
            "minQueryLength": 3,
            "resultLimit": 5
        },
        "contentTree": {
            "loadMoreLimit": 30,
            "childrenLoadMaxLimit": 200,
            "treeMaxDepth": 10,
            "allowedContentTypes": [],
            "ignoredContentTypes": [],
            "treeRootLocationId": 2,
            "contextualTreeRootLocationIds": [
                2,
                5,
                43,
                48,
                57
            ]
        },
        "imageEditor": {
            "config": {
                "actionGroups": {
                    "default": {
                        "label": "Default",
                        "actions": {
                            "crop": {
                                "priority": 300,
                                "buttons": {
                                    "1_1": {
                                        "label": "1:1",
                                        "ratio": {
                                            "x": 1,
                                            "y": 1
                                        },
                                        "priority": 0,
                                        "visible": true
                                    },
                                    "3_4": {
                                        "label": "3:4",
                                        "ratio": {
                                            "x": 3,
                                            "y": 4
                                        },
                                        "priority": 0,
                                        "visible": true
                                    },
                                    "4_3": {
                                        "label": "4:3",
                                        "ratio": {
                                            "x": 4,
                                            "y": 3
                                        },
                                        "priority": 0,
                                        "visible": true
                                    },
                                    "16_9": {
                                        "label": "16:9",
                                        "ratio": {
                                            "x": 16,
                                            "y": 9
                                        },
                                        "priority": 0,
                                        "visible": true
                                    },
                                    "custom": {
                                        "label": "Custom",
                                        "priority": 0,
                                        "visible": true
                                    }
                                },
                                "visible": true
                            },
                            "flip": {
                                "priority": 200,
                                "visible": true,
                                "buttons": []
                            },
                            "focal-point": {
                                "priority": 100,
                                "visible": true,
                                "buttons": []
                            }
                        }
                    }
                },
                "imageQuality": 0.92
            }
        }
    }
}

XML

<?xml version="1.0" encoding="UTF-8"?>
<ApplicationConfig media-type="application/vnd.ibexa.api.ApplicationConfig+xml">
	<multiFileUpload>
		<value key="locationMappings" />
		<value key="defaultMappings">
			<value>
				<value key="mimeTypes">
					<value>image/jpeg</value>
					<value>image/jpg</value>
					<value>image/gif</value>
					<value>image/png</value>
				</value>
				<value key="contentTypeIdentifier">image</value>
				<value key="contentFieldIdentifier">asset</value>
				<value key="nameFieldIdentifier">title</value>
			</value>
		</value>
		<value key="fallbackContentType">
			<value key="contentTypeIdentifier">image</value>
			<value key="contentFieldIdentifier">asset</value>
			<value key="nameFieldIdentifier">title</value>
		</value>
		<value key="maxFileSize">5242880</value>
	</multiFileUpload>
	<sortFieldMappings>
		<value key="PATH">LocationPath</value>
		<value key="PUBLISHED">DatePublished</value>
		<value key="MODIFIED">DateModified</value>
		<value key="SECTION">SectionIdentifier</value>
		<value key="DEPTH">LocationDepth</value>
		<value key="PRIORITY">LocationPriority</value>
		<value key="NAME">ContentName</value>
		<value key="NODE_ID">LocationId</value>
		<value key="CONTENTOBJECT_ID">ContentId</value>
	</sortFieldMappings>
	<sortOrderMappings>
		<value key="ASC">ascending</value>
		<value key="DESC">descending</value>
	</sortOrderMappings>
	<imageVariations>
		<value key="original" />
		<value key="reference">
			<value key="reference" />
			<value key="filters">
				<value key="geometry/scaledownonly">
					<value>600</value>
					<value>600</value>
				</value>
			</value>
		</value>
		<value key="small">
			<value key="reference">reference</value>
			<value key="filters">
				<value key="geometry/scaledownonly">
					<value>100</value>
					<value>100</value>
				</value>
			</value>
		</value>
		<value key="tiny">
			<value key="reference">reference</value>
			<value key="filters">
				<value key="geometry/scaledownonly">
					<value>30</value>
					<value>30</value>
				</value>
			</value>
		</value>
		<value key="medium">
			<value key="reference">reference</value>
			<value key="filters">
				<value key="geometry/scaledownonly">
					<value>200</value>
					<value>200</value>
				</value>
			</value>
		</value>
		<value key="large">
			<value key="reference">reference</value>
			<value key="filters">
				<value key="geometry/scaledownonly">
					<value>300</value>
					<value>300</value>
				</value>
			</value>
		</value>
		<value key="ezplatform_admin_ui_profile_picture_user_menu">
			<value key="reference">reference</value>
			<value key="filters">
				<value key="geometry/scaledownonly">
					<value>30</value>
					<value>30</value>
				</value>
				<value key="geometry/crop">
					<value>30</value>
					<value>30</value>
					<value>0</value>
					<value>0</value>
				</value>
			</value>
			<value key="post_processors" />
		</value>
	</imageVariations>
	<contentEditFormTemplates />
	<user>
		<user />
		<profile_picture_field />
	</user>
	<languages>
		<value key="mappings">
			<value key="eng-GB">
				<value key="name">English (United Kingdom)</value>
				<value key="id">2</value>
				<value key="languageCode">eng-GB</value>
				<value key="enabled">true</value>
			</value>
		</value>
		<value key="priority">
			<value>eng-GB</value>
		</value>
	</languages>
	<contentTypes>
		<value key="Content">
			<value>
				<value key="id">1</value>
				<value key="identifier">folder</value>
				<value key="name">Folder</value>
				<value key="isContainer">true</value>
				<value key="thumbnail">/bundles/ibexaadminui/img/ibexa-icons.svg#folder</value>
				<value key="href">/api/ibexa/v2/content/types/1</value>
			</value>
		</value>
		<value key="Users">
			<value>
				<value key="id">4</value>
				<value key="identifier">user</value>
				<value key="name">User</value>
				<value key="isContainer">false</value>
				<value key="thumbnail">/bundles/ibexaadminui/img/ibexa-icons.svg#user</value>
				<value key="href">/api/ibexa/v2/content/types/4</value>
			</value>
			<value>
				<value key="id">3</value>
				<value key="identifier">user_group</value>
				<value key="name">User group</value>
				<value key="isContainer">true</value>
				<value key="thumbnail">/bundles/ibexaadminui/img/ibexa-icons.svg#user_group</value>
				<value key="href">/api/ibexa/v2/content/types/3</value>
			</value>
		</value>
		<value key="Media">
			<value>
				<value key="id">13</value>
				<value key="identifier">image</value>
				<value key="name">Image</value>
				<value key="isContainer">false</value>
				<value key="thumbnail">/bundles/ibexaadminui/img/ibexa-icons.svg#image</value>
				<value key="href">/api/ibexa/v2/content/types/13</value>
			</value>
		</value>
	</contentTypes>
	<universalDiscoveryWidget>
		<value key="startingLocationId">1</value>
	</universalDiscoveryWidget>
	<subItems>
		<value key="limit">10</value>
	</subItems>
	<imageAssetMapping>
		<value key="contentTypeIdentifier">image</value>
		<value key="contentFieldIdentifier">image</value>
		<value key="nameFieldIdentifier">name</value>
		<value key="parentLocationId">51</value>
	</imageAssetMapping>
	<notifications>
		<value key="error">
			<value key="timeout">0</value>
		</value>
		<value key="warning">
			<value key="timeout">0</value>
		</value>
		<value key="info">
			<value key="timeout">0</value>
		</value>
		<value key="success">
			<value key="timeout">5000</value>
		</value>
	</notifications>
	<timezone>UTC</timezone>
	<dateFormat>
		<value key="fullDateTime">LLLL dd, yyyy HH:mm</value>
		<value key="fullDate">LLLL dd, yyyy</value>
		<value key="fullTime">HH:mm</value>
		<value key="shortDateTime">dd/MM/yyyy HH:mm</value>
		<value key="shortDate">dd/MM/yyyy</value>
		<value key="shortTime">HH:mm</value>
	</dateFormat>
	<autosave>
		<value key="enabled">false</value>
		<value key="interval">60000</value>
	</autosave>
	<userContentTypes>
		<value>user</value>
	</userContentTypes>
	<sections />
	<locations>
		<value key="media">43</value>
		<value key="contentStructure">2</value>
		<value key="users">5</value>
	</locations>
	<iconPaths>
		<value key="iconSets">
			<value key="public_icons">/bundles/ibexaadminui/img/ibexa-icons.svg</value>
			<value key="streamlineicons">/bundles/ibexaicons/img/all-icons.svg</value>
		</value>
		<value key="defaultIconSet">streamlineicons</value>
	</iconPaths>
	<backOfficeLanguage>en</backOfficeLanguage>
	<backOfficePath>/</backOfficePath>
	<suggestions>
		<value key="minQueryLength">3</value>
		<value key="resultLimit">5</value>
	</suggestions>
	<contentTree>
		<value key="loadMoreLimit">30</value>
		<value key="childrenLoadMaxLimit">200</value>
		<value key="treeMaxDepth">10</value>
		<value key="allowedContentTypes" />
		<value key="ignoredContentTypes" />
		<value key="treeRootLocationId">2</value>
		<value key="contextualTreeRootLocationIds">
			<value>2</value>
			<value>5</value>
			<value>43</value>
			<value>48</value>
			<value>57</value>
		</value>
	</contentTree>
	<imageEditor>
		<value key="config">
			<value key="actionGroups">
				<value key="default">
					<value key="label">Default</value>
					<value key="actions">
						<value key="crop">
							<value key="priority">300</value>
							<value key="buttons">
								<value key="1_1">
									<value key="label">1:1</value>
									<value key="ratio">
										<value key="x">1</value>
										<value key="y">1</value>
									</value>
									<value key="priority">0</value>
									<value key="visible">true</value>
								</value>
								<value key="3_4">
									<value key="label">3:4</value>
									<value key="ratio">
										<value key="x">3</value>
										<value key="y">4</value>
									</value>
									<value key="priority">0</value>
									<value key="visible">true</value>
								</value>
								<value key="4_3">
									<value key="label">4:3</value>
									<value key="ratio">
										<value key="x">4</value>
										<value key="y">3</value>
									</value>
									<value key="priority">0</value>
									<value key="visible">true</value>
								</value>
								<value key="16_9">
									<value key="label">16:9</value>
									<value key="ratio">
										<value key="x">16</value>
										<value key="y">9</value>
									</value>
									<value key="priority">0</value>
									<value key="visible">true</value>
								</value>
								<value key="custom">
									<value key="label">Custom</value>
									<value key="priority">0</value>
									<value key="visible">true</value>
								</value>
							</value>
							<value key="visible">true</value>
						</value>
						<value key="flip">
							<value key="priority">200</value>
							<value key="visible">true</value>
							<value key="buttons" />
						</value>
						<value key="focal-point">
							<value key="priority">100</value>
							<value key="visible">true</value>
							<value key="buttons" />
						</value>
					</value>
				</value>
			</value>
			<value key="imageQuality">0.920000</value>
		</value>
	</imageEditor>
</ApplicationConfig>

Customize configuration option

Config Providers are extendable and allows to add extra data to configuration, so custom Generators with abstraction layer have been also added. That allows to customize configuration parameter in REST for specific namespace. Namespace is a key used in service tag e.g.: multiFileUpload (ref: https://github.com/ibexa/admin-ui/blob/main/src/bundle/Resources/config/services/ui_config/common.yaml#L21).

Checklist:

  • Coding standards ($ composer fix-cs)
  • Ready for Code Review

@ciastektk ciastektk force-pushed the ibx-7275-exposed-base-admin-ui-configuration-in-rest-api branch from de08ce0 to 4ab0e0f Compare December 4, 2023 15:43
@ciastektk ciastektk requested a review from a team December 5, 2023 07:27
@ciastektk ciastektk added Doc needed The changes require some documentation Improvement Ready for review labels Dec 5, 2023
phpstan-baseline.neon Outdated Show resolved Hide resolved
Copy link
Member

@alongosz alongosz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Foremost I'm missing information what kind of response it forms, because there's no test coverage. Could you include in the description responses for XML and JSON formats?

@alongosz alongosz requested a review from a team December 5, 2023 10:32
@ciastektk ciastektk force-pushed the ibx-7275-exposed-base-admin-ui-configuration-in-rest-api branch from 265451b to 94705df Compare December 6, 2023 06:45
Copy link

sonarcloud bot commented Dec 6, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 2 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@webhdx webhdx requested a review from a team December 7, 2023 10:41
Copy link
Member

@alongosz alongosz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very well formed XML 💪 JSON probably too :)

Copy link
Contributor

@glye glye left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ciastektk Have you reviewed all data that could be returned for security implications, since this is not authenticated?
Is it public because that's easier, or because it strictly has to be?
Does it dump the entire config, or only what is strictly required by DAM?
Could you consider making it configurable, so those who don't need this for DAM can block it?

Some clients have reacted in the past about making content type info public, but that's already done in dedicated endpoints anyway, I think. So they'd have to disable rest entirely in the frontend to stop it.

@glye
Copy link
Contributor

glye commented Dec 8, 2023

If this dumps the entire config, another risk is if we later add some new config setting that is sensitive - and we forget that this endpoint is exposing all of it. A good reason to only expose what is specifically required.

@ciastektk
Copy link
Contributor Author

@glye, @mnocon, we had an internal discussion with the backend team. For now, could you please check that the current response to anonymous users does not contain sensitive data? We have a permissions system that should restrict content data for anonymous users.

@glye
Copy link
Contributor

glye commented Dec 11, 2023

@ciastektk, @mnocon I have checked (the output in the description) and not found anything that is dangerous by itself. Some "known unknowns" exist:

  1. Other setups and customisations might include additional config data that is vulnerable. We should warn users about this in all relevant places.
  2. Future changes we make might add new config data that is vulnerable. We should warn ourselves about this in all relevant places.
  3. The information might be usable for attacks when combined with an existing vulnerability. Typically ddos, but who knows. It's generally good to expose only what is strictly necessary.

Copy link
Contributor

@mnocon mnocon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've also looked into the data returned - there are only two differences:

  1. Data for Anonymous does not contain information about sections
  2. Data for Anonymous does not contain information about the current user

Both make sense to me

In case we're ok (for now) with this technical design - QA Approved!

@ciastektk
Copy link
Contributor Author

ciastektk commented Dec 11, 2023

We need to thing about next steps in terms of Providers, what kind of data should be exposed and of course how to secure current solution. This endpoint is very important because most of the data are used by UDW and frontend part changes of Image picker needs to be adjusted. For now, we decided to merge it as is.

@ciastektk ciastektk merged commit 3cb72e5 into main Dec 11, 2023
26 checks passed
@ciastektk ciastektk deleted the ibx-7275-exposed-base-admin-ui-configuration-in-rest-api branch December 11, 2023 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Doc needed The changes require some documentation Improvement QA approved
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants