Skip to content

Commit 344fb8e

Browse files
authored
Merge branch 'develop' into fix/rbac_existing_users_deleted_bug
2 parents d5c6182 + 455ee42 commit 344fb8e

File tree

11 files changed

+421
-338
lines changed

11 files changed

+421
-338
lines changed

docs/modules/ROOT/pages/developer-guide/configuration.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ must be granted to enble any user to create logs.
133133

134134
⚠️ * Load/Save from/to file are not logged (only from/to Database)
135135

136-
|loggingDatabase |string |neo4j |When loggingMode is set to anything
136+
|loggingDatabase |string |logs |When loggingMode is set to anything
137137
else than '0', the database to use for logging. Log records (nodes)
138138
will be created in this database.
139139

gallery/yarn.lock

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3042,12 +3042,19 @@ brace-expansion@^2.0.1:
30423042
dependencies:
30433043
balanced-match "^1.0.0"
30443044

3045-
braces@^3.0.2, braces@~3.0.2:
3045+
braces@^3.0.3:
3046+
version "3.0.3"
3047+
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
3048+
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
3049+
dependencies:
3050+
fill-range "^7.1.1"
3051+
3052+
braces@~3.0.2:
30463053
version "3.0.2"
30473054
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
30483055
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
30493056
dependencies:
3050-
fill-range "^7.0.1"
3057+
fill-range "^7.1.1"
30513058

30523059
browser-process-hrtime@^1.0.0:
30533060
version "1.0.0"
@@ -4530,9 +4537,9 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
45304537
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
45314538

45324539
fast-loops@^1.1.3:
4533-
version "1.1.3"
4534-
resolved "https://registry.yarnpkg.com/fast-loops/-/fast-loops-1.1.3.tgz#ce96adb86d07e7bf9b4822ab9c6fac9964981f75"
4535-
integrity sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g==
4540+
version "1.1.4"
4541+
resolved "https://registry.yarnpkg.com/fast-loops/-/fast-loops-1.1.4.tgz#61bc77d518c0af5073a638c6d9d5c7683f069ce2"
4542+
integrity sha512-8dbd3XWoKCTms18ize6JmQF1SFnnfj5s0B7rRry22EofgMu7B6LKHVh+XfFqFGsqnbH54xgeO83PzpKI+ODhlg==
45364543

45374544
fast-shallow-equal@^1.0.0:
45384545
version "1.0.0"
@@ -4606,10 +4613,17 @@ filesize@^8.0.6:
46064613
resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8"
46074614
integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==
46084615

4609-
fill-range@^7.0.1:
4610-
version "7.0.1"
4611-
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
4612-
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
4616+
fill-range@^7.1.1:
4617+
version "7.1.1"
4618+
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
4619+
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
4620+
dependencies:
4621+
to-regex-range "^5.0.1"
4622+
4623+
fill-range@^7.1.1:
4624+
version "7.1.1"
4625+
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
4626+
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
46134627
dependencies:
46144628
to-regex-range "^5.0.1"
46154629

@@ -4677,9 +4691,9 @@ flatted@^3.1.0:
46774691
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
46784692

46794693
follow-redirects@^1.0.0:
4680-
version "1.15.4"
4681-
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.4.tgz#cdc7d308bf6493126b17ea2191ea0ccf3e535adf"
4682-
integrity sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==
4694+
version "1.15.6"
4695+
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
4696+
integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
46834697

46844698
for-each@^0.3.3:
46854699
version "0.3.3"
@@ -6476,11 +6490,11 @@ methods@~1.1.2:
64766490
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
64776491

64786492
micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5:
6479-
version "4.0.5"
6480-
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
6481-
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
6493+
version "4.0.8"
6494+
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
6495+
integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
64826496
dependencies:
6483-
braces "^3.0.2"
6497+
braces "^3.0.3"
64846498
picomatch "^2.3.1"
64856499

64866500
[email protected], "mime-db@>= 1.43.0 < 2":

src/application/ApplicationThunks.ts

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,6 @@ export const handleSharedDashboardsThunk = () => (dispatch: any) => {
261261
if (dashboardDatabase) {
262262
dispatch(setStandaloneDashboardDatabase(dashboardDatabase));
263263
}
264-
265264
if (urlParams.get('credentials')) {
266265
setWelcomeScreenOpen(false);
267266
const connection = decodeURIComponent(urlParams.get('credentials'));
@@ -271,32 +270,6 @@ export const handleSharedDashboardsThunk = () => (dispatch: any) => {
271270
const database = connection.split('@')[1].split(':')[0];
272271
const url = connection.split('@')[1].split(':')[1];
273272
const port = connection.split('@')[1].split(':')[2];
274-
// if (url == password) {
275-
// // Special case where a connect link is generated without a password.
276-
// // Here, the format is parsed incorrectly and we open the connection window instead.
277-
// dispatch(setConnectionProperties(protocol, url, port, database, username.split('@')[0], ''));
278-
// dispatch(
279-
// setShareDetailsFromUrl(
280-
// type,
281-
// id,
282-
// standalone,
283-
// protocol,
284-
// url,
285-
// port,
286-
// database,
287-
// username.split('@')[0],
288-
// '',
289-
// dashboardDatabase,
290-
// true
291-
// )
292-
// );
293-
// setDashboardToLoadAfterConnecting(id);
294-
// window.history.pushState({}, document.title, window.location.pathname);
295-
// dispatch(setConnectionModalOpen(true));
296-
// dispatch(setWelcomeScreenOpen(false));
297-
// // window.history.pushState({}, document.title, "/");
298-
// return;
299-
// }
300273

301274
dispatch(setConnectionModalOpen(false));
302275
dispatch(
@@ -327,7 +300,7 @@ export const handleSharedDashboardsThunk = () => (dispatch: any) => {
327300
setShareDetailsFromUrl(
328301
type,
329302
id,
330-
undefined,
303+
standalone,
331304
undefined,
332305
undefined,
333306
undefined,
@@ -385,6 +358,7 @@ export const onConfirmLoadSharedDashboardThunk = () => (dispatch: any, getState:
385358
}
386359
if (shareDetails.standalone == true) {
387360
dispatch(setStandaloneMode(true));
361+
localStorage.setItem('standaloneShared', 'true'); // EDGE CASE: redirect SSO removes the shareDetails when redirecting
388362
}
389363
dispatch(resetShareDetails());
390364
} catch (e) {
@@ -455,10 +429,13 @@ export const loadApplicationConfigThunk = () => async (dispatch: any, getState:
455429
dispatch(setSSOEnabled(config.ssoEnabled, state.application.cachedSSODiscoveryUrl));
456430
dispatch(setSSOProviders(config.ssoProviders));
457431

432+
// Check if we are in standalone mode
433+
// const standaloneShared = localStorage.getItem('standaloneShared') == 'true'; // EDGE case: from url param it could happen that we lose the value due to SSO redirect
458434
const { standalone } = config;
435+
// || standaloneShared;
436+
459437
// if a dashboard database was previously set, remember to use it.
460438
const dashboardDatabase = state.application.standaloneDashboardDatabase;
461-
462439
dispatch(
463440
setStandaloneEnabled(
464441
standalone,
@@ -478,6 +455,7 @@ export const loadApplicationConfigThunk = () => async (dispatch: any, getState:
478455
config.standaloneDatabaseList
479456
)
480457
);
458+
localStorage.removeItem('standaloneShared');
481459

482460
dispatch(setLoggingMode(config.loggingMode));
483461
dispatch(setLoggingDatabase(config.loggingDatabase));

src/chart/ChartUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ export const downloadCSV = (rows) => {
164164
headers.forEach((header) => {
165165
// Parse value
166166
let value = row[header];
167-
if (value && value.low) {
167+
if (value && 'low' in value) {
168168
value = value.low;
169169
}
170170
csv += `${JSON.stringify(value)}`;

src/chart/table/TableChart.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { DataGrid, GridColumnVisibilityModel } from '@mui/x-data-grid';
33
import { ChartProps } from '../Chart';
44
import {
55
evaluateRulesOnDict,
6+
evaluateSingleRuleOnDict,
67
generateClassDefinitionsBasedOnRules,
78
useStyleRules,
89
} from '../../extensions/styling/StyleRuleEvaluator';
@@ -243,6 +244,7 @@ export const NeoTableChart = (props: ChartProps) => {
243244
ColumnSortedDescendingIcon: () => <></>,
244245
ColumnSortedAscendingIcon: () => <></>,
245246
},
247+
// TODO: if mixing and matching row and cell styling, row rules MUST be set first or will not populate correctly
246248
getRowClassName: (params) => {
247249
return ['row color', 'row text color']
248250
.map((e) => {
@@ -253,7 +255,19 @@ export const NeoTableChart = (props: ChartProps) => {
253255
getCellClassName: (params) => {
254256
return ['cell color', 'cell text color']
255257
.map((e) => {
256-
return `rule${evaluateRulesOnDict({ [params.field]: params.value }, styleRules, [e])}`;
258+
let trueRulesList = [''];
259+
let trueRule;
260+
for (const [index, rule] of styleRules.entries()) {
261+
if (rule.targetField) {
262+
if (rule.targetField === params.field) {
263+
trueRule = `rule${evaluateSingleRuleOnDict({ [rule.field]: params.row[rule.field] }, rule, index, [e])}`;
264+
}
265+
} else {
266+
trueRule = `rule${evaluateSingleRuleOnDict({ [params.field]: params.value }, rule, index, [e])}`;
267+
}
268+
trueRulesList.push(trueRule);
269+
}
270+
return trueRulesList.join(' ');
257271
})
258272
.join(' ');
259273
},

src/extensions/styling/StyleRuleCreationModal.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,35 @@ export const NeoCustomReportStyleModal = ({
338338
}}
339339
fluid
340340
/>
341+
<Autocomplete
342+
className='n-align-middle n-inline-block n-w-5/12 n-pr-1'
343+
disableClearable={true}
344+
id={`autocomplete-label-type${index}`}
345+
size='small'
346+
noOptionsText='*Specify an exact field name'
347+
options={createFieldVariableSuggestions().filter((e) =>
348+
e.toLowerCase().includes(rule.targetField)
349+
)}
350+
value={rule.targetField ? rule.targetField : (rule.field ? rule.field : '')}
351+
inputValue={rule.targetField ? rule.targetField : (rule.field ? rule.field : '')}
352+
popupIcon={<></>}
353+
style={{ minWidth: 125, visibility: rule.customization.includes("cell") ? 'visible' : 'hidden', display: rule.customization.includes("cell") ? '' : 'none' }}
354+
onInputChange={(event, value) => {
355+
updateRuleField(index, 'targetField', value);
356+
}}
357+
onChange={(event, newValue) => {
358+
updateRuleField(index, 'targetField', newValue);
359+
}}
360+
renderInput={(params) => (
361+
<TextField
362+
{...params}
363+
placeholder='Target field name...'
364+
InputLabelProps={{ shrink: true }}
365+
style={{ padding: '6px 0 7px' }}
366+
size={'small'}
367+
/>
368+
)}
369+
/>
341370
<TextInput
342371
className='n-align-middle n-inline-block n-w-1/12 n-pr-1'
343372
style={{ minWidth: 30 }}

src/extensions/styling/StyleRuleEvaluator.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,21 +63,27 @@ export const evaluateRulesOnDict = (dict, rules, customizations) => {
6363
}
6464
for (const [index, rule] of rules.entries()) {
6565
// Only check customizations that are specified
66-
if (customizations.includes(rule.customization)) {
67-
// if the row contains the specified field...
68-
if (dict[rule.field] !== undefined && dict[rule.field] !== null) {
69-
const realValue = dict[rule.field].low ? dict[rule.field].low : dict[rule.field];
70-
const ruleValue = rule.value;
71-
if (evaluateCondition(realValue, rule.condition, ruleValue)) {
72-
return index;
73-
}
74-
}
75-
}
66+
return evaluateSingleRuleOnDict (dict, rule, index, customizations)
7667
}
7768
// If no rules are met, return not found (index=-1)
7869
return -1;
7970
};
8071

72+
export const evaluateSingleRuleOnDict = (dict, rule, ruleIndex, customizations) => {
73+
if (customizations.includes(rule.customization)) {
74+
// if the row contains the specified field...
75+
if (dict[rule.field] !== undefined && dict[rule.field] !== null) {
76+
const realValue = dict[rule.field].low ? dict[rule.field].low : dict[rule.field];
77+
const ruleValue = rule.value;
78+
if (evaluateCondition(realValue, rule.condition, ruleValue)) {
79+
return ruleIndex;
80+
}
81+
}
82+
}
83+
return -1;
84+
}
85+
86+
8187
/**
8288
* Evaluates the specified rule set on a node object returned by the Neo4j driver.
8389
* @param node - the node representation returned by the Neo4j driver.

src/report/ReportRecordProcessing.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -269,16 +269,17 @@ function RenderArray(value, transposedTable = false) {
269269
mapped = value.map((v, i) => {
270270
return RenderSubValue(v) + (i < value.length - 1 ? ', ' : '');
271271
});
272+
} else {
273+
// Render Node and Relationship objects, which will look like a Path
274+
mapped = value.map((v, i) => {
275+
return (
276+
<span key={String(`k${i}`) + v}>
277+
{RenderSubValue(v)}
278+
{i < value.length - 1 && !valueIsNode(v) && !valueIsRelationship(v) ? <span>, </span> : <></>}
279+
</span>
280+
);
281+
});
272282
}
273-
// Render Node and Relationship objects, which will look like a Path
274-
mapped = value.map((v, i) => {
275-
return (
276-
<span key={String(`k${i}`) + v}>
277-
{RenderSubValue(v)}
278-
{i < value.length - 1 && !valueIsNode(v) && !valueIsRelationship(v) ? <span>, </span> : <></>}
279-
</span>
280-
);
281-
});
282283
return mapped;
283284
}
284285

ssl/Dockerfile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# build stage
2+
FROM neo4jlabs/neodash:latest AS neodash
3+
4+
ENV NGINX_HTTPS_PORT=5443
5+
6+
USER root
7+
8+
RUN mkdir -p /etc/nginx/certs
9+
10+
RUN --mount=type=secret,id=NEODASH_SSL_KEY \
11+
base64 -d /run/secrets/NEODASH_SSL_KEY > /etc/nginx/certs/key.pem
12+
13+
RUN --mount=type=secret,id=NEODASH_SSL_CERT \
14+
base64 -d /run/secrets/NEODASH_SSL_CERT > /etc/nginx/certs/cert.pem
15+
16+
COPY default.conf /etc/nginx/templates/default.conf.template
17+
COPY default.conf /etc/nginx/conf.d/
18+
19+
RUN chown -R nginx:nginx /etc/nginx
20+
21+
USER nginx
22+
EXPOSE $NGINX_HTTPS_PORT
23+
24+
HEALTHCHECK CMD curl --fail "https://localhost:$NGINX_HTTPS_PORT" || exit 1
25+
LABEL version="1.0"

ssl/default.conf

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
server {
2+
listen ${NGINX_PORT};
3+
server_name localhost;
4+
include mime.types;
5+
location / {
6+
root /usr/share/nginx/html;
7+
try_files $uri $uri/ /index.html;
8+
index index.html index.htm;
9+
}
10+
# redirect server error pages to the static page /50x.html
11+
# Note: This is optional, depending on the implementation in React
12+
error_page 500 502 503 504 /50x.html;
13+
location = /50x.html {
14+
root /usr/share/nginx/html;
15+
}
16+
}
17+
server {
18+
listen 5443 ssl;
19+
ssl_certificate /etc/nginx/certs/cert.pem;
20+
ssl_certificate_key /etc/nginx/certs/key.pem;
21+
server_name localhost;
22+
include mime.types;
23+
location / {
24+
root /usr/share/nginx/html;
25+
try_files $uri $uri/ /index.html;
26+
index index.html index.htm;
27+
}
28+
# redirect server error pages to the static page /50x.html
29+
# Note: This is optional, depending on the implementation in React
30+
error_page 500 502 503 504 /50x.html;
31+
location = /50x.html {
32+
root /usr/share/nginx/html;
33+
}
34+
}

0 commit comments

Comments
 (0)