From 7267ba64851ef2714e1b1c72b0a5d5de3218a431 Mon Sep 17 00:00:00 2001 From: Its-treason <39559178+Its-treason@users.noreply.github.com> Date: Sun, 22 Oct 2023 21:54:17 +0200 Subject: [PATCH 1/3] feat(#682): Enforce environment variable strictness --- .../EnvironmentVariables/StyledWrapper.js | 6 +- .../EnvironmentVariables/index.js | 210 +++++++++--------- .../EnvironmentVariables/reducer.js | 52 ----- 3 files changed, 113 insertions(+), 155 deletions(-) delete mode 100644 packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/reducer.js diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js index 64b11b25c..7eec1394c 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js @@ -13,10 +13,12 @@ const Wrapper = styled.div` padding: 4px 10px; &:nth-child(1), - &:nth-child(4), - &:nth-child(5) { + &:nth-child(4) { width: 70px; } + &:nth-child(5) { + width: 40px; + } &:nth-child(2) { width: 25%; diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js index 748626768..6ac7f8e4c 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js @@ -1,68 +1,79 @@ -import React, { useReducer } from 'react'; +import React from 'react'; import toast from 'react-hot-toast'; import cloneDeep from 'lodash/cloneDeep'; import { IconTrash } from '@tabler/icons'; import { useTheme } from 'providers/Theme'; import { useDispatch } from 'react-redux'; import { saveEnvironment } from 'providers/ReduxStore/slices/collections/actions'; -import reducer from './reducer'; import SingleLineEditor from 'components/SingleLineEditor'; import StyledWrapper from './StyledWrapper'; +import { useFormik } from 'formik'; +import * as Yup from 'yup'; +import { uuid } from 'utils/common'; const EnvironmentVariables = ({ environment, collection }) => { const dispatch = useDispatch(); const { storedTheme } = useTheme(); - const [state, reducerDispatch] = useReducer(reducer, { hasChanges: false, variables: environment.variables || [] }); - const { variables, hasChanges } = state; - const saveChanges = () => { - dispatch(saveEnvironment(cloneDeep(variables), environment.uid, collection.uid)) - .then(() => { - toast.success('Changes saved successfully'); - reducerDispatch({ - type: 'CHANGES_SAVED' - }); + const formik = useFormik({ + enableReinitialize: true, + initialValues: environment.variables || [], + validationSchema: Yup.array().of( + Yup.object({ + enabled: Yup.boolean(), + name: Yup.string() + .required('Name cannot be empty') + .matches(/^[^\d]\w*$/, 'Name contains invalid characters') + .trim(), + secret: Yup.boolean(), + type: Yup.string(), + uid: Yup.string(), + value: Yup.string().trim() }) - .catch(() => toast.error('An error occurred while saving the changes')); + ), + onSubmit: (values) => { + if (!formik.dirty) { + toast.error('Nothing to save'); + return; + } + + dispatch(saveEnvironment(cloneDeep(values), environment.uid, collection.uid)) + .then(() => { + toast.success('Changes saved successfully'); + formik.resetForm({ values }); + }) + .catch(() => toast.error('An error occurred while saving the changes')); + } + }); + + const ErrorMessage = ({ name }) => { + const meta = formik.getFieldMeta(name); + console.log(name, meta); + if (!meta.error) { + return null; + } + + return ( + + ); }; const addVariable = () => { - reducerDispatch({ - type: 'ADD_VAR' - }); + const newVariable = { + uid: uuid(), + name: '', + value: '', + type: 'text', + secret: false, + enabled: true + }; + formik.setFieldValue(formik.values.length, newVariable, false); }; - const handleVarChange = (e, _variable, type) => { - const variable = cloneDeep(_variable); - switch (type) { - case 'name': { - variable.name = e.target.value; - break; - } - case 'value': { - variable.value = e.target.value; - break; - } - case 'enabled': { - variable.enabled = e.target.checked; - break; - } - case 'secret': { - variable.secret = e.target.checked; - break; - } - } - reducerDispatch({ - type: 'UPDATE_VAR', - variable - }); - }; - - const handleRemoveVars = (variable) => { - reducerDispatch({ - type: 'DELETE_VAR', - variable - }); + const handleRemoveVar = (id) => { + formik.setValues(formik.values.filter((variable) => variable.uid !== id)); }; return ( @@ -78,55 +89,57 @@ const EnvironmentVariables = ({ environment, collection }) => { - {variables && variables.length - ? variables.map((variable, index) => { - return ( - - - handleVarChange(e, variable, 'enabled')} - /> - - - handleVarChange(e, variable, 'name')} - /> - - - handleVarChange({ target: { value: newValue } }, variable, 'value')} - collection={collection} - /> - - - handleVarChange(e, variable, 'secret')} - /> - - - - - - ); - }) - : null} + {formik.values.map((variable, index) => ( + + + + + + + + + + formik.setFieldValue(`${index}.value`, newValue, true)} + /> + + + + + + + + + ))} @@ -137,12 +150,7 @@ const EnvironmentVariables = ({ environment, collection }) => {
-
diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/reducer.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/reducer.js deleted file mode 100644 index a5aa3e0c1..000000000 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/reducer.js +++ /dev/null @@ -1,52 +0,0 @@ -import produce from 'immer'; -import find from 'lodash/find'; -import filter from 'lodash/filter'; -import { uuid } from 'utils/common'; - -const reducer = (state, action) => { - switch (action.type) { - case 'ADD_VAR': { - return produce(state, (draft) => { - draft.variables.push({ - uid: uuid(), - name: '', - value: '', - type: 'text', - secret: false, - enabled: true - }); - draft.hasChanges = true; - }); - } - - case 'UPDATE_VAR': { - return produce(state, (draft) => { - const variable = find(draft.variables, (v) => v.uid === action.variable.uid); - variable.name = action.variable.name; - variable.value = action.variable.value; - variable.enabled = action.variable.enabled; - variable.secret = action.variable.secret; - draft.hasChanges = true; - }); - } - - case 'DELETE_VAR': { - return produce(state, (draft) => { - draft.variables = filter(draft.variables, (v) => v.uid !== action.variable.uid); - draft.hasChanges = true; - }); - } - - case 'CHANGES_SAVED': { - return produce(state, (draft) => { - draft.hasChanges = false; - }); - } - - default: { - return state; - } - } -}; - -export default reducer; From 827df18c627e5ad1b0ffeb01f409136c585e6819 Mon Sep 17 00:00:00 2001 From: Its-treason <39559178+Its-treason@users.noreply.github.com> Date: Wed, 25 Oct 2023 23:13:37 +0200 Subject: [PATCH 2/3] feat(#682): Add validation for request vars & dynamic vars --- .../EnvironmentVariables/index.js | 2 +- .../RequestPane/Vars/VarsTable/index.js | 17 +++++++++-- .../src/components/RequestPane/Vars/index.js | 30 ------------------- packages/bruno-js/src/bru.js | 14 +++++++++ 4 files changed, 30 insertions(+), 33 deletions(-) diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js index 6ac7f8e4c..dfd93be33 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js @@ -23,7 +23,7 @@ const EnvironmentVariables = ({ environment, collection }) => { enabled: Yup.boolean(), name: Yup.string() .required('Name cannot be empty') - .matches(/^[^\d]\w*$/, 'Name contains invalid characters') + .matches(/^(?!\d)\w*$/, 'Name contains invalid characters') .trim(), secret: Yup.boolean(), type: Yup.string(), diff --git a/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js b/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js index 6ee760978..77785e47a 100644 --- a/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js +++ b/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js @@ -8,6 +8,7 @@ import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collection import SingleLineEditor from 'components/SingleLineEditor'; import Tooltip from 'components/Tooltip'; import StyledWrapper from './StyledWrapper'; +import toast from 'react-hot-toast'; const VarsTable = ({ item, collection, vars, varType }) => { const dispatch = useDispatch(); @@ -29,7 +30,19 @@ const VarsTable = ({ item, collection, vars, varType }) => { const _var = cloneDeep(v); switch (type) { case 'name': { - _var.name = e.target.value; + const value = e.target.value; + + if (/^(?!\d).*$/.test(value) === false) { + toast.error('Variable names must not start with a number!'); + return; + } + + if (/^\w*$/.test(value) === false) { + toast.error('Variable contains invalid character! Variables must only contain alpha-numeric characters.'); + return; + } + + _var.name = value; break; } case 'value': { @@ -88,7 +101,7 @@ const VarsTable = ({ item, collection, vars, varType }) => { {vars && vars.length - ? vars.map((_var, index) => { + ? vars.map((_var) => { return ( diff --git a/packages/bruno-app/src/components/RequestPane/Vars/index.js b/packages/bruno-app/src/components/RequestPane/Vars/index.js index b63c08801..500ebb25b 100644 --- a/packages/bruno-app/src/components/RequestPane/Vars/index.js +++ b/packages/bruno-app/src/components/RequestPane/Vars/index.js @@ -1,42 +1,12 @@ import React from 'react'; import get from 'lodash/get'; -import { useDispatch } from 'react-redux'; -import { updateRequestScript, updateResponseScript } from 'providers/ReduxStore/slices/collections'; -import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; -import { useTheme } from 'providers/Theme'; import VarsTable from './VarsTable'; import StyledWrapper from './StyledWrapper'; const Vars = ({ item, collection }) => { - const dispatch = useDispatch(); const requestVars = item.draft ? get(item, 'draft.request.vars.req') : get(item, 'request.vars.req'); const responseVars = item.draft ? get(item, 'draft.request.vars.res') : get(item, 'request.vars.res'); - const { storedTheme } = useTheme(); - - const onRequestScriptEdit = (value) => { - dispatch( - updateRequestScript({ - script: value, - itemUid: item.uid, - collectionUid: collection.uid - }) - ); - }; - - const onResponseScriptEdit = (value) => { - dispatch( - updateResponseScript({ - script: value, - itemUid: item.uid, - collectionUid: collection.uid - }) - ); - }; - - const onRun = () => dispatch(sendRequest(item, collection.uid)); - const onSave = () => dispatch(saveRequest(item.uid, collection.uid)); - return (
diff --git a/packages/bruno-js/src/bru.js b/packages/bruno-js/src/bru.js index 3cd9e8f5f..5eaae4cca 100644 --- a/packages/bruno-js/src/bru.js +++ b/packages/bruno-js/src/bru.js @@ -59,10 +59,24 @@ class Bru { throw new Error('Key is required'); } + if (/^(?!\d)\w*$/.test(key) === false) { + throw new Error( + `Variable name: "${key}" contains invalid characters!` + + ' Names must only contain alpha-numeric characters and cannot start with a digit.' + ); + } + this.collectionVariables[key] = value; } getVar(key) { + if (/^(?!\d)\w*$/.test(key) === false) { + throw new Error( + `Variable name: "${key}" contains invalid characters!` + + ' Names must only contain alpha-numeric characters and cannot start with a digit.' + ); + } + return this.collectionVariables[key]; } } From d52163ceb38799c753733440ef814a86ebe4dec5 Mon Sep 17 00:00:00 2001 From: Its-treason <39559178+Its-treason@users.noreply.github.com> Date: Wed, 25 Oct 2023 23:30:31 +0200 Subject: [PATCH 3/3] test: Fix failing test 'should parse the json file' --- packages/bruno-lang/v2/tests/fixtures/request.bru | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bruno-lang/v2/tests/fixtures/request.bru b/packages/bruno-lang/v2/tests/fixtures/request.bru index 22168b194..813a519b6 100644 --- a/packages/bruno-lang/v2/tests/fixtures/request.bru +++ b/packages/bruno-lang/v2/tests/fixtures/request.bru @@ -66,7 +66,7 @@ body:sparql { body:form-urlencoded { apikey: secret - numbers: +91998877665 + numbers: %2B91998877665 ~message: hello }