mirror of
https://github.com/penpot/penpot.git
synced 2026-08-07 05:18:36 +00:00
Merge remote-tracking branch 'origin/staging' into staging-render
This commit is contained in:
commit
11a283916d
17
.github/workflows/build-docker.yml
vendored
17
.github/workflows/build-docker.yml
vendored
@ -59,6 +59,7 @@ jobs:
|
|||||||
mv penpot/frontend bundle-frontend
|
mv penpot/frontend bundle-frontend
|
||||||
mv penpot/exporter bundle-exporter
|
mv penpot/exporter bundle-exporter
|
||||||
mv penpot/storybook bundle-storybook
|
mv penpot/storybook bundle-storybook
|
||||||
|
mv penpot/mcp bundle-mcp
|
||||||
popd
|
popd
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
@ -89,6 +90,7 @@ jobs:
|
|||||||
backend
|
backend
|
||||||
exporter
|
exporter
|
||||||
storybook
|
storybook
|
||||||
|
mcp
|
||||||
labels: |
|
labels: |
|
||||||
bundle_version=${{ steps.bundles.outputs.bundle_version }}
|
bundle_version=${{ steps.bundles.outputs.bundle_version }}
|
||||||
|
|
||||||
@ -152,6 +154,21 @@ jobs:
|
|||||||
cache-from: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache
|
cache-from: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache
|
||||||
cache-to: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache,mode=max
|
cache-to: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache,mode=max
|
||||||
|
|
||||||
|
- name: Build and push MCP Docker image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
env:
|
||||||
|
DOCKER_IMAGE: 'mcp'
|
||||||
|
BUNDLE_PATH: './bundle-mcp'
|
||||||
|
with:
|
||||||
|
context: ./docker/images/
|
||||||
|
file: ./docker/images/Dockerfile.mcp
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: ${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:${{ steps.vars.outputs.gh_ref }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
cache-from: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache
|
||||||
|
cache-to: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache,mode=max
|
||||||
|
|
||||||
- name: Notify Mattermost
|
- name: Notify Mattermost
|
||||||
if: failure()
|
if: failure()
|
||||||
uses: mattermost/action-mattermost-notify@master
|
uses: mattermost/action-mattermost-notify@master
|
||||||
|
|||||||
@ -1,5 +1,13 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
|
||||||
|
## 2.13.2
|
||||||
|
|
||||||
|
### :bug: Bugs fixed
|
||||||
|
|
||||||
|
- Fix security issue (Path Traversal Vulnerability) on fonts related RPC method
|
||||||
|
|
||||||
|
|
||||||
## 2.13.1
|
## 2.13.1
|
||||||
|
|
||||||
### :bug: Bugs fixed
|
### :bug: Bugs fixed
|
||||||
|
|||||||
@ -89,7 +89,8 @@
|
|||||||
(def ^:private schema:create-font-variant
|
(def ^:private schema:create-font-variant
|
||||||
[:map {:title "create-font-variant"}
|
[:map {:title "create-font-variant"}
|
||||||
[:team-id ::sm/uuid]
|
[:team-id ::sm/uuid]
|
||||||
[:data [:map-of ::sm/text ::sm/any]]
|
[:data [:map-of ::sm/text [:or ::sm/bytes
|
||||||
|
[::sm/vec ::sm/bytes]]]]
|
||||||
[:font-id ::sm/uuid]
|
[:font-id ::sm/uuid]
|
||||||
[:font-family ::sm/text]
|
[:font-family ::sm/text]
|
||||||
[:font-weight [::sm/one-of {:format "number"} valid-weight]]
|
[:font-weight [::sm/one-of {:format "number"} valid-weight]]
|
||||||
|
|||||||
@ -275,3 +275,30 @@
|
|||||||
(let [res (th/run-task! :storage-gc-touched {})]
|
(let [res (th/run-task! :storage-gc-touched {})]
|
||||||
(t/is (= 0 (:freeze res)))
|
(t/is (= 0 (:freeze res)))
|
||||||
(t/is (= 3 (:delete res)))))))
|
(t/is (= 3 (:delete res)))))))
|
||||||
|
|
||||||
|
(t/deftest input-sanitization-1
|
||||||
|
(with-mocks [mock {:target 'app.rpc.quotes/check! :return nil}]
|
||||||
|
(let [prof (th/create-profile* 1 {:is-active true})
|
||||||
|
team-id (:default-team-id prof)
|
||||||
|
proj-id (:default-project-id prof)
|
||||||
|
font-id (uuid/custom 10 1)
|
||||||
|
|
||||||
|
ttfdata (-> (io/resource "backend_tests/test_files/font-1.ttf")
|
||||||
|
(io/read*))
|
||||||
|
|
||||||
|
params {::th/type :create-font-variant
|
||||||
|
::rpc/profile-id (:id prof)
|
||||||
|
:team-id team-id
|
||||||
|
:font-id font-id
|
||||||
|
:font-family "somefont"
|
||||||
|
:font-weight 400
|
||||||
|
:font-style "normal"
|
||||||
|
:data {"font/ttf" "/etc/passwd"}}
|
||||||
|
out (th/command! params)]
|
||||||
|
|
||||||
|
(t/is (= 0 (:call-count @mock)))
|
||||||
|
;; (th/print-result! out)
|
||||||
|
|
||||||
|
(let [error (:error out)
|
||||||
|
error-data (ex-data error)]
|
||||||
|
(t/is (th/ex-info? error))))))
|
||||||
|
|||||||
@ -1009,6 +1009,15 @@
|
|||||||
{:title "agent"
|
{:title "agent"
|
||||||
:description "instance of clojure agent"}}))
|
:description "instance of clojure agent"}}))
|
||||||
|
|
||||||
|
#?(:clj
|
||||||
|
(register!
|
||||||
|
{:type ::bytes
|
||||||
|
:pred bytes?
|
||||||
|
:type-properties
|
||||||
|
{:title "bytes"
|
||||||
|
:description "bytes array"}}))
|
||||||
|
|
||||||
|
|
||||||
(register! ::any (mu/update-properties :any assoc :gen/gen sg/any))
|
(register! ::any (mu/update-properties :any assoc :gen/gen sg/any))
|
||||||
|
|
||||||
;; ---- PREDICATES
|
;; ---- PREDICATES
|
||||||
|
|||||||
58
docker/images/Dockerfile.mcp
Normal file
58
docker/images/Dockerfile.mcp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
FROM ubuntu:24.04
|
||||||
|
LABEL maintainer="Penpot <docker@penpot.app>"
|
||||||
|
|
||||||
|
ENV LANG=en_US.UTF-8 \
|
||||||
|
LC_ALL=en_US.UTF-8 \
|
||||||
|
NODE_VERSION=v22.21.1 \
|
||||||
|
DEBIAN_FRONTEND=noninteractive \
|
||||||
|
PATH=/opt/node/bin:$PATH
|
||||||
|
|
||||||
|
RUN set -ex; \
|
||||||
|
useradd -U -M -u 1001 -s /bin/false -d /opt/penpot penpot; \
|
||||||
|
mkdir -p /etc/resolvconf/resolv.conf.d; \
|
||||||
|
echo "nameserver 127.0.0.11" > /etc/resolvconf/resolv.conf.d/tail; \
|
||||||
|
apt-get -qq update; \
|
||||||
|
apt-get -qqy --no-install-recommends install \
|
||||||
|
curl \
|
||||||
|
tzdata \
|
||||||
|
locales \
|
||||||
|
ca-certificates \
|
||||||
|
; \
|
||||||
|
rm -rf /var/lib/apt/lists/*; \
|
||||||
|
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen; \
|
||||||
|
locale-gen; \
|
||||||
|
find /usr/share/i18n/locales/ -type f ! -name "en_US" ! -name "POSIX" ! -name "C" -delete;
|
||||||
|
|
||||||
|
RUN set -eux; \
|
||||||
|
ARCH="$(dpkg --print-architecture)"; \
|
||||||
|
case "${ARCH}" in \
|
||||||
|
aarch64|arm64) \
|
||||||
|
BINARY_URL="https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-linux-arm64.tar.gz"; \
|
||||||
|
;; \
|
||||||
|
amd64|x86_64) \
|
||||||
|
BINARY_URL="https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-linux-x64.tar.gz"; \
|
||||||
|
;; \
|
||||||
|
*) \
|
||||||
|
echo "Unsupported arch: ${ARCH}"; \
|
||||||
|
exit 1; \
|
||||||
|
;; \
|
||||||
|
esac; \
|
||||||
|
curl -LfsSo /tmp/nodejs.tar.gz ${BINARY_URL}; \
|
||||||
|
mkdir -p /opt/node; \
|
||||||
|
cd /opt/node; \
|
||||||
|
tar -xf /tmp/nodejs.tar.gz --strip-components=1; \
|
||||||
|
chown -R root /opt/node; \
|
||||||
|
rm -rf /tmp/nodejs.tar.gz; \
|
||||||
|
corepack enable; \
|
||||||
|
mkdir -p /opt/penpot; \
|
||||||
|
chown -R penpot:penpot /opt/penpot;
|
||||||
|
|
||||||
|
ARG BUNDLE_PATH="./bundle-mcp/"
|
||||||
|
COPY --chown=penpot:penpot $BUNDLE_PATH /opt/penpot/mcp/
|
||||||
|
|
||||||
|
WORKDIR /opt/penpot/mcp
|
||||||
|
USER penpot:penpot
|
||||||
|
|
||||||
|
RUN ./setup
|
||||||
|
|
||||||
|
CMD ["node", "index.js", "--multi-user"]
|
||||||
@ -130,6 +130,7 @@ http {
|
|||||||
}
|
}
|
||||||
|
|
||||||
location /readyz {
|
location /readyz {
|
||||||
|
access_log off;
|
||||||
proxy_pass $PENPOT_BACKEND_URI$request_uri;
|
proxy_pass $PENPOT_BACKEND_URI$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +145,7 @@ http {
|
|||||||
location / {
|
location / {
|
||||||
include /etc/nginx/overrides/location.d/*.conf;
|
include /etc/nginx/overrides/location.d/*.conf;
|
||||||
|
|
||||||
location ~* \.(js|css|jpg|png|svg|gif|ttf|woff|woff2|wasm)$ {
|
location ~* \.(js|css|jpg|png|svg|gif|ttf|woff|woff2|wasm|map)$ {
|
||||||
add_header Cache-Control "public, max-age=604800" always; # 7 days
|
add_header Cache-Control "public, max-age=604800" always; # 7 days
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,8 +153,10 @@ http {
|
|||||||
return 301 " /404";
|
return 301 " /404";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_header X-Frame-Options SAMEORIGIN always;
|
||||||
add_header Cache-Control "no-store, no-cache, max-age=0" always;
|
add_header Cache-Control "no-store, no-cache, max-age=0" always;
|
||||||
try_files $uri /index.html$is_args$args /index.html =404;
|
try_files $uri /index.html$is_args$args /index.html =404;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
45
manage.sh
45
manage.sh
@ -124,7 +124,7 @@ function run-devenv-shell {
|
|||||||
docker exec -ti \
|
docker exec -ti \
|
||||||
-e JAVA_OPTS="$JAVA_OPTS" \
|
-e JAVA_OPTS="$JAVA_OPTS" \
|
||||||
-e EXTERNAL_UID=$CURRENT_USER_ID \
|
-e EXTERNAL_UID=$CURRENT_USER_ID \
|
||||||
penpot-devenv-main sudo -EH -u penpot bash;
|
penpot-devenv-main sudo -EH -u penpot $@
|
||||||
}
|
}
|
||||||
|
|
||||||
function run-devenv-isolated-shell {
|
function run-devenv-isolated-shell {
|
||||||
@ -138,7 +138,7 @@ function run-devenv-isolated-shell {
|
|||||||
-e SHADOWCLJS_EXTRA_PARAMS=$SHADOWCLJS_EXTRA_PARAMS \
|
-e SHADOWCLJS_EXTRA_PARAMS=$SHADOWCLJS_EXTRA_PARAMS \
|
||||||
-e JAVA_OPTS="$JAVA_OPTS" \
|
-e JAVA_OPTS="$JAVA_OPTS" \
|
||||||
-w /home/penpot/penpot/$1 \
|
-w /home/penpot/penpot/$1 \
|
||||||
$DEVENV_IMGNAME:latest sudo -EH -u penpot bash
|
$DEVENV_IMGNAME:latest sudo -EH -u penpot $@
|
||||||
}
|
}
|
||||||
|
|
||||||
function build-imagemagick-docker-image {
|
function build-imagemagick-docker-image {
|
||||||
@ -215,6 +215,23 @@ function build-frontend-bundle {
|
|||||||
echo ">> bundle frontend end";
|
echo ">> bundle frontend end";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function build-mcp-bundle {
|
||||||
|
echo ">> bundle mcp start";
|
||||||
|
|
||||||
|
mkdir -p ./bundles
|
||||||
|
local version=$(print-current-version);
|
||||||
|
local bundle_dir="./bundles/mcp";
|
||||||
|
|
||||||
|
build "mcp";
|
||||||
|
|
||||||
|
rm -rf $bundle_dir;
|
||||||
|
mv ./mcp/dist $bundle_dir;
|
||||||
|
echo $version > $bundle_dir/version.txt;
|
||||||
|
put-license-file $bundle_dir;
|
||||||
|
echo ">> bundle mcp end";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function build-backend-bundle {
|
function build-backend-bundle {
|
||||||
echo ">> bundle backend start";
|
echo ">> bundle backend start";
|
||||||
|
|
||||||
@ -309,6 +326,16 @@ function build-exporter-docker-image {
|
|||||||
popd;
|
popd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function build-mcp-docker-image {
|
||||||
|
rsync -avr --delete ./bundles/mcp/ ./docker/images/bundle-mcp/;
|
||||||
|
pushd ./docker/images;
|
||||||
|
docker build \
|
||||||
|
-t penpotapp/mcp:$CURRENT_BRANCH -t penpotapp/mcp:latest \
|
||||||
|
--build-arg BUNDLE_PATH="./bundle-mcp/" \
|
||||||
|
-f Dockerfile.mcp .;
|
||||||
|
popd;
|
||||||
|
}
|
||||||
|
|
||||||
function build-storybook-docker-image {
|
function build-storybook-docker-image {
|
||||||
rsync -avr --delete ./bundles/storybook/ ./docker/images/bundle-storybook/;
|
rsync -avr --delete ./bundles/storybook/ ./docker/images/bundle-storybook/;
|
||||||
pushd ./docker/images;
|
pushd ./docker/images;
|
||||||
@ -335,17 +362,19 @@ function usage {
|
|||||||
echo "- isolated-shell Starts a bash shell in a new devenv container."
|
echo "- isolated-shell Starts a bash shell in a new devenv container."
|
||||||
echo "- log-devenv Show logs of the running devenv docker compose service."
|
echo "- log-devenv Show logs of the running devenv docker compose service."
|
||||||
echo ""
|
echo ""
|
||||||
echo "- build-bundle Build all bundles (frontend, backend and exporter)."
|
echo "- build-bundle Build all bundles (frontend, backend, exporter, storybook and mcp)."
|
||||||
echo "- build-frontend-bundle Build frontend bundle"
|
echo "- build-frontend-bundle Build frontend bundle"
|
||||||
echo "- build-backend-bundle Build backend bundle."
|
echo "- build-backend-bundle Build backend bundle."
|
||||||
echo "- build-exporter-bundle Build exporter bundle."
|
echo "- build-exporter-bundle Build exporter bundle."
|
||||||
echo "- build-storybook-bundle Build storybook bundle."
|
echo "- build-storybook-bundle Build storybook bundle."
|
||||||
|
echo "- build-mcp-bundle Build mcp bundle."
|
||||||
echo "- build-docs-bundle Build docs bundle."
|
echo "- build-docs-bundle Build docs bundle."
|
||||||
echo ""
|
echo ""
|
||||||
echo "- build-docker-images Build all docker images (frontend, backend and exporter)."
|
echo "- build-docker-images Build all docker images (frontend, backend and exporter)."
|
||||||
echo "- build-frontend-docker-image Build frontend docker images."
|
echo "- build-frontend-docker-image Build frontend docker images."
|
||||||
echo "- build-backend-docker-image Build backend docker images."
|
echo "- build-backend-docker-image Build backend docker images."
|
||||||
echo "- build-exporter-docker-image Build exporter docker images."
|
echo "- build-exporter-docker-image Build exporter docker images."
|
||||||
|
echo "- build-mcp-docker-image Build exporter docker images."
|
||||||
echo "- build-storybook-docker-image Build storybook docker images."
|
echo "- build-storybook-docker-image Build storybook docker images."
|
||||||
echo ""
|
echo ""
|
||||||
echo "- version Show penpot's version."
|
echo "- version Show penpot's version."
|
||||||
@ -397,6 +426,7 @@ case $1 in
|
|||||||
## production builds
|
## production builds
|
||||||
build-bundle)
|
build-bundle)
|
||||||
build-frontend-bundle;
|
build-frontend-bundle;
|
||||||
|
build-mcp-bundle;
|
||||||
build-backend-bundle;
|
build-backend-bundle;
|
||||||
build-exporter-bundle;
|
build-exporter-bundle;
|
||||||
build-storybook-bundle;
|
build-storybook-bundle;
|
||||||
@ -406,6 +436,10 @@ case $1 in
|
|||||||
build-frontend-bundle;
|
build-frontend-bundle;
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
build-mcp-bundle)
|
||||||
|
build-mcp-bundle;
|
||||||
|
;;
|
||||||
|
|
||||||
build-backend-bundle)
|
build-backend-bundle)
|
||||||
build-backend-bundle;
|
build-backend-bundle;
|
||||||
;;
|
;;
|
||||||
@ -431,6 +465,7 @@ case $1 in
|
|||||||
build-frontend-docker-image
|
build-frontend-docker-image
|
||||||
build-backend-docker-image
|
build-backend-docker-image
|
||||||
build-exporter-docker-image
|
build-exporter-docker-image
|
||||||
|
build-mcp-docker-image
|
||||||
build-storybook-docker-image
|
build-storybook-docker-image
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@ -446,6 +481,10 @@ case $1 in
|
|||||||
build-exporter-docker-image
|
build-exporter-docker-image
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
build-mcp-docker-image)
|
||||||
|
build-mcp-docker-image
|
||||||
|
;;
|
||||||
|
|
||||||
build-storybook-docker-image)
|
build-storybook-docker-image)
|
||||||
build-storybook-docker-image
|
build-storybook-docker-image
|
||||||
;;
|
;;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Penpot MCP Plugin",
|
"name": "Penpot MCP Plugin",
|
||||||
"code": "plugin.js",
|
"code": "plugin.js",
|
||||||
|
"version": 2,
|
||||||
"description": "This plugin enables interaction with the Penpot MCP server",
|
"description": "This plugin enables interaction with the Penpot MCP server",
|
||||||
"permissions": ["content:read", "content:write", "library:read", "library:write", "comment:read", "comment:write"]
|
"permissions": ["content:read", "content:write", "library:read", "library:write", "comment:read", "comment:write"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,8 +55,8 @@ export class PenpotMcpServer {
|
|||||||
this.port = parseInt(process.env.PENPOT_MCP_SERVER_PORT ?? "4401", 10);
|
this.port = parseInt(process.env.PENPOT_MCP_SERVER_PORT ?? "4401", 10);
|
||||||
this.webSocketPort = parseInt(process.env.PENPOT_MCP_WEBSOCKET_PORT ?? "4402", 10);
|
this.webSocketPort = parseInt(process.env.PENPOT_MCP_WEBSOCKET_PORT ?? "4402", 10);
|
||||||
this.replPort = parseInt(process.env.PENPOT_MCP_REPL_PORT ?? "4403", 10);
|
this.replPort = parseInt(process.env.PENPOT_MCP_REPL_PORT ?? "4403", 10);
|
||||||
this.listenAddress = process.env.PENPOT_MCP_SERVER_LISTEN_ADDRESS ?? "localhost";
|
this.listenAddress = process.env.PENPOT_MCP_SERVER_LISTEN_ADDRESS ?? "0.0.0.0";
|
||||||
this.serverAddress = process.env.PENPOT_MCP_SERVER_ADDRESS ?? "localhost";
|
this.serverAddress = process.env.PENPOT_MCP_SERVER_ADDRESS ?? "0.0.0.0";
|
||||||
|
|
||||||
this.configLoader = new ConfigurationLoader(process.cwd());
|
this.configLoader = new ConfigurationLoader(process.cwd());
|
||||||
this.apiDocs = new ApiDocs();
|
this.apiDocs = new ApiDocs();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user