Skip to content

Commit 2abc840

Browse files
authored
Merge branch 'dev' into embedded-app-authentication
2 parents e013a68 + d4546e9 commit 2abc840

File tree

8 files changed

+143
-41
lines changed

8 files changed

+143
-41
lines changed

client/packages/lowcoder/src/comps/generators/uiCompBuilder.tsx

+72-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { BoolCodeControl } from "comps/controls/codeControl";
1+
import { BoolCodeControl, StringControl } from "comps/controls/codeControl";
22
import React, { ReactNode, useContext, useRef } from "react";
33
import { ExternalEditorContext } from "util/context/ExternalEditorContext";
44
import { Comp, CompParams, MultiBaseComp } from "lowcoder-core";
@@ -22,10 +22,14 @@ import {
2222
MethodConfigsType,
2323
withMethodExposing,
2424
} from "./withMethodExposing";
25+
import { Section } from "lowcoder-design";
26+
import { trans } from "i18n";
2527

2628
export type NewChildren<ChildrenCompMap extends Record<string, Comp<unknown>>> =
2729
ChildrenCompMap & {
2830
hidden: InstanceType<typeof BoolCodeControl>;
31+
className: InstanceType<typeof StringControl>;
32+
dataTestId: InstanceType<typeof StringControl>;
2933
};
3034

3135
export function HidableView(props: {
@@ -50,12 +54,51 @@ export function HidableView(props: {
5054
}
5155
}
5256

57+
export function ExtendedComponentView(props: {
58+
children: JSX.Element | React.ReactNode;
59+
className: string;
60+
dataTestId: string;
61+
}) {
62+
if (!props.className && !props.dataTestId) {
63+
return <>{props.children}</>;
64+
}
65+
66+
return (
67+
<div className={props.className} data-testid={props.dataTestId}>
68+
{props.children}
69+
</div>
70+
);
71+
}
72+
73+
export function ExtendedPropertyView<
74+
ChildrenCompMap extends Record<string, Comp<unknown>>,
75+
>(props: {
76+
children: JSX.Element | React.ReactNode,
77+
childrenMap: NewChildren<ChildrenCompMap>
78+
}
79+
) {
80+
return (
81+
<>
82+
{props.children}
83+
<Section name={trans("prop.component")}>
84+
{props.childrenMap.className?.propertyView({ label: trans("prop.className") })}
85+
{props.childrenMap.dataTestId?.propertyView({ label: trans("prop.dataTestId") })}
86+
</Section>
87+
</>
88+
);
89+
}
90+
5391
export function uiChildren<
5492
ChildrenCompMap extends Record<string, Comp<unknown>>,
5593
>(
5694
childrenMap: ToConstructor<ChildrenCompMap>
5795
): ToConstructor<NewChildren<ChildrenCompMap>> {
58-
return { ...childrenMap, hidden: BoolCodeControl } as any;
96+
return {
97+
...childrenMap,
98+
hidden: BoolCodeControl,
99+
className: StringControl,
100+
dataTestId: StringControl
101+
} as any;
59102
}
60103

61104
type ViewReturn = ReactNode;
@@ -89,10 +132,22 @@ export class UICompBuilder<
89132
setPropertyViewFn(
90133
propertyViewFn: PropertyViewFnTypeForComp<NewChildren<ChildrenCompMap>>
91134
) {
92-
this.propertyViewFn = propertyViewFn;
135+
this.propertyViewFn = this.decoratePropertyViewFn(propertyViewFn);
93136
return this;
94137
}
95138

139+
decoratePropertyViewFn(
140+
propertyViewFn: PropertyViewFnTypeForComp<NewChildren<ChildrenCompMap>>
141+
): PropertyViewFnTypeForComp<NewChildren<ChildrenCompMap>> {
142+
return (childrenMap, dispatch) => {
143+
return (
144+
<ExtendedPropertyView childrenMap={childrenMap}>
145+
{propertyViewFn(childrenMap, dispatch)}
146+
</ExtendedPropertyView>
147+
);
148+
};
149+
}
150+
96151
setExposeStateConfigs(
97152
configs: ExposingConfig<ChildrenToComp<ChildrenCompMap>>[]
98153
) {
@@ -110,8 +165,11 @@ export class UICompBuilder<
110165
}
111166

112167
build() {
113-
if (this.childrenMap.hasOwnProperty("hidden")) {
114-
throw new Error("already has hidden");
168+
const reservedProps = ["hidden", "className", "dataTestId"];
169+
for (const reservedProp of reservedProps) {
170+
if (this.childrenMap.hasOwnProperty(reservedProp)) {
171+
throw new Error(`Property »${reservedProp}« is reserved and must not be implemented in components!`);
172+
}
115173
}
116174
const newChildrenMap = uiChildren(this.childrenMap);
117175
const builder = this;
@@ -122,7 +180,7 @@ export class UICompBuilder<
122180
ToNodeType<NewChildren<ChildrenCompMap>>
123181
> {
124182
ref: React.RefObject<HTMLDivElement> = React.createRef();
125-
183+
126184
override parseChildrenFromValue(
127185
params: CompParams<ToDataType<NewChildren<ChildrenCompMap>>>
128186
): NewChildren<ChildrenCompMap> {
@@ -185,8 +243,13 @@ function UIView(props: { comp: any; viewFn: any }) {
185243
//END ADD BY FRED
186244

187245
return (
188-
<HidableView hidden={childrenProps.hidden as boolean}>
189-
{props.viewFn(childrenProps, comp.dispatch)}
190-
</HidableView>
246+
<ExtendedComponentView
247+
className={childrenProps.className as string}
248+
dataTestId={childrenProps.dataTestId as string}
249+
>
250+
<HidableView hidden={childrenProps.hidden as boolean}>
251+
{props.viewFn(childrenProps, comp.dispatch)}
252+
</HidableView>
253+
</ExtendedComponentView>
191254
);
192255
}

client/packages/lowcoder/src/i18n/locales/de.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,10 @@ export const de: typeof en = {
195195
"showBody": "Hauptbereich zeigen",
196196
"showFooter": "Fußbereich anzeigen",
197197
"maskClosable": "Zum Schließen auf \"Schließen\" klicken",
198-
"showMask": "Maske darstellen"
198+
"showMask": "Maske darstellen",
199+
"component": "Komponente",
200+
"className": "Klasse",
201+
"dataTestId": "Test ID",
199202
},
200203
"autoHeightProp": {
201204
...en.autoHeightProp,

client/packages/lowcoder/src/i18n/locales/en.ts

+3
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@ export const en = {
211211
"baseURL": "Lowcoder API Base URL",
212212
"horizontal": "Horizontal",
213213
"minHorizontalWidth": "Minimum Horizontal Width",
214+
"component": "Component",
215+
"className": "Class",
216+
"dataTestId": "Test ID",
214217
},
215218
"autoHeightProp": {
216219
"auto": "Auto",

deploy/docker/Dockerfile

+23-7
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ RUN chmod +x /lowcoder/api-service/*.sh
2525
## To create a separate image out of it, build it with:
2626
## DOCKER_BUILDKIT=1 docker build -f deploy/docker/Dockerfile -t lowcoderorg/lowcoder-ce-api-service --target lowcoder-ce-api-service .
2727
##
28-
FROM eclipse-temurin:17-jammy as lowcoder-ce-api-service
28+
FROM eclipse-temurin:17-jammy AS lowcoder-ce-api-service
2929
LABEL maintainer="lowcoder"
3030

3131
RUN apt-get update && apt-get install -y --no-install-recommends gosu \
@@ -49,7 +49,7 @@ CMD [ "/bin/bash" , "/lowcoder/api-service/entrypoint.sh" ]
4949
##
5050
## Build lowcoder node service
5151
##
52-
FROM ubuntu:jammy as build-node-service
52+
FROM ubuntu:jammy AS build-node-service
5353

5454
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y curl ca-certificates build-essential gnupg
5555

@@ -80,7 +80,7 @@ RUN chmod +x /lowcoder/node-service/*.sh
8080
## To create a separate image out of it, build it with:
8181
## DOCKER_BUILDKIT=1 docker build -f deploy/docker/Dockerfile -t lowcoderorg/lowcoder-ce-node-service --target lowcoder-ce-node-service .
8282
##
83-
FROM ubuntu:jammy as lowcoder-ce-node-service
83+
FROM ubuntu:jammy AS lowcoder-ce-node-service
8484
LABEL maintainer="lowcoder"
8585

8686
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y curl ca-certificates gnupg
@@ -145,7 +145,7 @@ RUN yarn build
145145
## To create a separate image out of it, build it with:
146146
## DOCKER_BUILDKIT=1 docker build -f deploy/docker/Dockerfile -t lowcoderorg/lowcoder-ce-frontend --target lowcoder-ce-frontend .
147147
##
148-
FROM nginx:1.25.1 as lowcoder-ce-frontend
148+
FROM nginx:1.25.1 AS lowcoder-ce-frontend
149149
LABEL maintainer="lowcoder"
150150

151151
# Change default nginx user into lowcoder user and remove default nginx config
@@ -189,7 +189,10 @@ EXPOSE 3443
189189
FROM lowcoder-ce-frontend
190190
LABEL maintainer="lowcoder"
191191

192-
RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y curl ca-certificates gnupg
192+
RUN apt-get update && apt-get upgrade -y \
193+
&& DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y curl ca-certificates gnupg \
194+
&& rm -rf /var/cache/apt/lists /var/lib/apt/lists/* /var/log/dpkg.log \
195+
&& apt-get clean
193196

194197
# Add nodejs repo and keys
195198
RUN mkdir -p /etc/apt/keyrings \
@@ -211,8 +214,10 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-instal
211214
nodejs \
212215
openjdk-17-jdk-headless \
213216
&& npm install -g yarn \
214-
&& rm -rf /var/cache/apt/lists \
215-
&& mkdir -p /lowcoder/assets
217+
&& rm -rf /var/cache/apt/lists /var/lib/apt/lists/* /var/log/dpkg.log \
218+
&& mkdir -p /lowcoder/assets \
219+
&& apt-get clean \
220+
&& rm -rf /tmp/*
216221

217222
# Add lowcoder api-service
218223
COPY --chown=lowcoder:lowcoder --from=lowcoder-ce-api-service /lowcoder/api-service /lowcoder/api-service
@@ -227,6 +232,17 @@ COPY --chown=lowcoder:lowcoder deploy/docker/all-in-one/etc /lowcoder/etc
227232
# Add startup script
228233
COPY --chown=lowcoder:lowcoder deploy/docker/all-in-one/entrypoint.sh /lowcoder/entrypoint.sh
229234

235+
# Fixes for OpenShift compatibility (after all files are copied)
236+
RUN echo \
237+
&& adduser lowcoder root \
238+
&& mkdir -p /lowcoder-stacks \
239+
&& for i in /lowcoder-stacks /lowcoder/assets /lowcoder/api-service/logs /lowcoder/etc/supervisord; do \
240+
chmod -R g+rw "$i"; \
241+
chown -R lowcoder:root "$i"; \
242+
done \
243+
&& chown -R lowcoder:root /var/log \
244+
&& chmod -R g+rw /run /etc/nginx /var/cache/nginx /var/log
245+
230246
EXPOSE 27017
231247
EXPOSE 3000
232248
EXPOSE 3443

deploy/docker/all-in-one/entrypoint.sh

+15-6
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ export USER_ID=${LOWCODER_PUID:=9001}
66
export GROUP_ID=${LOWCODER_PGID:=9001}
77

88
# Update ID of lowcoder user if required
9-
if [ ! `id --user lowcoder` -eq ${USER_ID} ]; then
9+
if [ ! "$(id --user lowcoder)" -eq ${USER_ID} ]; then
1010
usermod --uid ${USER_ID} lowcoder
1111
echo "ID for lowcoder user changed to: ${USER_ID}"
1212
fi;
1313

1414
# Update ID of lowcoder group if required
15-
if [ ! `id --group lowcoder` -eq ${GROUP_ID} ]; then
15+
if [ ! "$(id --group lowcoder)" -eq ${GROUP_ID} ]; then
1616
groupmod --gid ${GROUP_ID} lowcoder
1717
echo "ID for lowcoder group changed to: ${GROUP_ID}"
1818
fi;
1919

2020
# Update host on which mongo is supposed to listen
21-
# If LOWCODER_MONGODB_EXPOSED is true, it will isten on all interfaces
21+
# If LOWCODER_MONGODB_EXPOSED is true, it will listen on all interfaces
2222
if [ "${LOWCODER_MONGODB_EXPOSED}" = "true" ]; then
2323
export MONGO_LISTEN_HOST="0.0.0.0"
2424
else
@@ -38,8 +38,10 @@ mkdir -p ${LOGS}/redis \
3838
${DATA}/mongodb \
3939
${CERT}
4040

41-
# Update owner of logs and data
42-
chown -R ${USER_ID}:${GROUP_ID} /lowcoder-stacks/ /lowcoder/etc
41+
# Update owner of logs and data - do not try if not running as root (OpenShift)
42+
if [ "$(id -u)" -eq 0 ]; then
43+
chown -R "${USER_ID}:${GROUP_ID}" /lowcoder-stacks/ /lowcoder/etc
44+
fi
4345

4446
# Enable services
4547
SUPERVISOR_AVAILABLE="/lowcoder/etc/supervisord/conf-available"
@@ -73,8 +75,15 @@ fi;
7375

7476
# Enable frontend if configured to run
7577
if [ "${LOWCODER_FRONTEND_ENABLED:=true}" = "true" ]; then
76-
ln ${SUPERVISOR_AVAILABLE}/20-frontend.conf ${SUPERVISOR_ENABLED}/20-frontend.conf
78+
ln ${SUPERVISOR_AVAILABLE}/20-frontend.conf ${SUPERVISOR_ENABLED}/20-frontend.conf
7779
fi;
7880

81+
# disable user directive if image is running non-root (Openshift)
82+
if [ "$(id -u)" -ne 0 ]; then
83+
for i in "${SUPERVISOR_ENABLED}"/*.conf; do
84+
sed -Ei 's/^\s*user=.*$//' "$i"
85+
done
86+
fi
87+
7988
# Handle CMD command
8089
"$@"

deploy/docker/all-in-one/etc/supervisord.conf

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
; supervisor config file
22

33
[unix_http_server]
4-
file=/var/run/supervisor.sock ; (the path to the socket file)
5-
chmod=0700 ; sockef file mode (default 0700)
4+
file = /var/run/supervisor.sock ; (the path to the socket file)
5+
chmod = 0700 ; socket file mode (default 0700)
66

77
;[inet_http_server] ; inet (TCP) server disabled by default
88
;port=*:9001 ; (ip_address:port specifier, *:port for all iface)
99
;username=user ; (default is no username (open server))
1010
;password=123 ; (default is no password (open server))
1111

1212
[supervisord]
13-
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
14-
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
15-
childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP)
13+
logfile = /dev/null ; (no logfile, stdout only; default $CWD/supervisord.log)
14+
pidfile = /var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
15+
childlogdir = /var/log/supervisor ; ('AUTO' child log dir, default $TEMP)
16+
logfile_maxbytes = 0
1617
stdout_logfile_maxbytes = 0
1718
stderr_logfile_maxbytes = 0
1819

@@ -23,7 +24,7 @@ stderr_logfile_maxbytes = 0
2324
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
2425

2526
[supervisorctl]
26-
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket
27+
serverurl = unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket
2728

2829
; The [include] section can just contain the "files" setting. This
2930
; setting can list multiple files (separated by whitespace or

deploy/docker/api-service/entrypoint.sh

+12-8
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ export GROUP_ID="${LOWCODER_PGID:=9001}"
99
echo "Initializing api-service..."
1010
/lowcoder/api-service/init.sh
1111

12-
if [ -z $JAVA_HOME ]; then
13-
JAVA_HOME=`dirname $(dirname $(readlink -f $(which javac)))`
12+
if [ -z "$JAVA_HOME" ]; then
13+
JAVA_HOME=$(dirname "$(dirname "$(readlink -f "$(which javac)")")")
1414
fi;
1515
APP_JAR="${APP_JAR:=/lowcoder/api-service/lowcoder-api-service.jar}"
1616
JAVA_OPTS="${JAVA_OPTS:=}"
@@ -19,16 +19,20 @@ CONTEXT_PATH=${CONTEXT_PATH:=/}
1919

2020
echo
2121
echo "Running lowcoder api-server with:"
22-
echo " user id: ${USER_ID}"
23-
echo " group id: ${GROUP_ID}"
2422
echo " base path: ${CONTEXT_PATH}"
23+
24+
if [ "$(id -u)" -eq 0 ]; then
25+
# only use su if its possible, suppress for containers running non-root
26+
echo " user id: ${USER_ID}"
27+
echo " group id: ${GROUP_ID}"
28+
GOSU="gosu ${USER_ID}:${GROUP_ID}"
29+
fi
2530
echo
26-
${JAVA_HOME}/bin/java -version
31+
"${JAVA_HOME}/bin/java" -version
2732
echo
2833

2934
cd /lowcoder/api-service
30-
31-
exec gosu ${USER_ID}:${GROUP_ID} ${JAVA_HOME}/bin/java \
35+
exec $GOSU "${JAVA_HOME}/bin/java" \
3236
-Djava.util.prefs.userRoot=/tmp \
3337
-Djava.security.egd=file:/dev/./urandom \
3438
-Dhttps.protocols=TLSv1.1,TLSv1.2 \
@@ -37,5 +41,5 @@ exec gosu ${USER_ID}:${GROUP_ID} ${JAVA_HOME}/bin/java \
3741
--add-opens java.base/java.nio=ALL-UNNAMED \
3842
${JAVA_OPTS} \
3943
-Dpf4j.pluginsDir=/lowcoder/api-service/plugins \
40-
-jar ${APP_JAR} --spring.webflux.base-path=${CONTEXT_PATH} ${CUSTOM_APP_PROPERTIES}
44+
-jar "${APP_JAR}" --spring.webflux.base-path="${CONTEXT_PATH}" ${CUSTOM_APP_PROPERTIES}
4145

deploy/docker/node-service/entrypoint.sh

+7-4
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@ cd /lowcoder/node-service/app
1515
echo
1616
echo "Running Lowcoder node-service with:"
1717
echo " API service host: ${API_HOST}"
18-
echo " user id: ${USER_ID}"
19-
echo " group id: ${GROUP_ID}"
18+
if [ "$(id -u)" -eq 0 ]; then
19+
# only use su if its possible, suppress for containers running non-root
20+
echo " user id: ${USER_ID}"
21+
echo " group id: ${GROUP_ID}"
22+
GOSU="gosu ${USER_ID}:${GROUP_ID}"
23+
fi
2024
echo
2125

22-
exec gosu ${USER_ID}:${GROUP_ID} yarn start
23-
26+
exec $GOSU yarn start

0 commit comments

Comments
 (0)