diff --git a/backend/go-app/walkoff.go b/backend/go-app/walkoff.go index 8da2f602..aac4c7e8 100644 --- a/backend/go-app/walkoff.go +++ b/backend/go-app/walkoff.go @@ -2597,7 +2597,7 @@ func executeSingleAction(resp http.ResponseWriter, request *http.Request) { if user.Role == "org-reader" { log.Printf("[WARNING] Org-reader doesn't have access to execute single action: %s (%s)", user.Username, user.Id) - resp.WriteHeader(401) + resp.WriteHeader(403) resp.Write([]byte(`{"success": false, "reason": "Read only user"}`)) return } diff --git a/frontend/package.json b/frontend/package.json index 99cef706..600cb60f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,10 +1,11 @@ { "name": "shuffler", "homepage": "https://shuffler.io", - "version": "1.1.0", + "version": "1.1.4", "private": true, "dependencies": { "@babel/core": "^7.15.8", + "@codemirror/commands": "^6.2.2", "@emotion/is-prop-valid": "^1.1.1", "@emotion/react": "^11.7.0", "@emotion/styled": "^11.6.0", diff --git a/frontend/src/components/Files.jsx b/frontend/src/components/Files.jsx index 09ca4547..5a7e92ac 100644 --- a/frontend/src/components/Files.jsx +++ b/frontend/src/components/Files.jsx @@ -35,7 +35,7 @@ import CodeEditor from "../components/ShuffleCodeEditor.jsx"; import theme from "../theme"; const Files = (props) => { - const { globalUrl, userdata, serverside, selectedOrganization, } = props; + const { globalUrl, userdata, serverside, selectedOrganization, isCloud, } = props; const [files, setFiles] = React.useState([]); const [selectedNamespace, setSelectedNamespace] = React.useState("default"); @@ -504,6 +504,7 @@ const Files = (props) => { />} { "efe4c3fe-84a1-4821-a84f-23a6cfe8e72d", "", "https://graph.microsoft.com", - ["Mail.ReadWrite"], + ["Mail.ReadWrite", "Mail.Send"], admin_consent, ); } else if (selectedApp.name.toLowerCase() == "gmail") { diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index c123e631..ec25e360 100644 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -166,6 +166,7 @@ const ParsedAction = (props) => { lastSaved, setLastSaved, setShowVideo, + toolsAppId, //expansionModalOpen, //setExpansionModalOpen, } = props; @@ -1520,6 +1521,8 @@ const ParsedAction = (props) => { const shufflecode = fieldCount !== count ? null : ( { - const { globalUrl, fieldCount, setFieldCount, actionlist, changeActionParameterCodeMirror, expansionModalOpen, setExpansionModalOpen, codedata, setcodedata, isFileEditor, runUpdateText } = props + const { globalUrl, fieldCount, setFieldCount, actionlist, changeActionParameterCodeMirror, expansionModalOpen, setExpansionModalOpen, codedata, setcodedata, isFileEditor, runUpdateText, toolsAppId } = props const [localcodedata, setlocalcodedata] = React.useState(codedata === undefined || codedata === null || codedata.length === 0 ? "" : codedata); // const {codelang, setcodelang} = props + const [validation, setValidation] = React.useState(false); const [expOutput, setExpOutput] = React.useState(" "); const [linewrap, setlinewrap] = React.useState(true); @@ -607,8 +609,9 @@ const CodeEditor = (props) => { } // Shuffle Tools 1.2.0 (in most cases?) - const appid = "3e2bdf9d5069fe3f4746c29d68785a6a" - const actiondata = {"description":"Repeats the call parameter","id":"","name":"repeat_back_to_me","label":"","node_type":"","environment":"","sharing":false,"private_id":"","public_id":"","app_id":"3e2bdf9d5069fe3f4746c29d68785a6a","tags":null,"authentication":[],"tested":false,"parameters":[{"description":"The message to repeat","id":"","name":"call","example":"REPEATING: Hello world","value":inputdata,"multiline":true,"options":null,"action_field":"","variant":"STATIC_VALUE","required":true,"configuration":false,"tags":null,"schema":{"type":"string"},"skip_multicheck":false,"value_replace":null,"unique_toggled":false,"autocompleted":false}],"execution_variable":{"description":"","id":"","name":"","value":""},"returns":{"description":"","example":"","id":"","schema":{"type":"string"}},"authentication_id":"","example":"","auth_not_required":false,"source_workflow":"","run_magic_output":false,"run_magic_input":false,"execution_delay":0,"app_name":"Shuffle Tools","app_version":"1.2.0","selectedAuthentication":{}} + const appid = toolsAppId !== undefined && toolsAppId !== null && toolsAppId.length > 0 ? toolsAppId : "3e2bdf9d5069fe3f4746c29d68785a6a" + + const actiondata = {"description":"Repeats the call parameter","id":"","name":"repeat_back_to_me","label":"","node_type":"","environment":"","sharing":false,"private_id":"","public_id":"","app_id": appid,"tags":null,"authentication":[],"tested":false,"parameters":[{"description":"The message to repeat","id":"","name":"call","example":"REPEATING: Hello world","value":inputdata,"multiline":true,"options":null,"action_field":"","variant":"STATIC_VALUE","required":true,"configuration":false,"tags":null,"schema":{"type":"string"},"skip_multicheck":false,"value_replace":null,"unique_toggled":false,"autocompleted":false}],"execution_variable":{"description":"","id":"","name":"","value":""},"returns":{"description":"","example":"","id":"","schema":{"type":"string"}},"authentication_id":"","example":"","auth_not_required":false,"source_workflow":"","run_magic_output":false,"run_magic_input":false,"execution_delay":0,"app_name":"Shuffle Tools","app_version":"1.2.0","selectedAuthentication":{}} setExecutionResult({ "valid": false, @@ -618,7 +621,7 @@ const CodeEditor = (props) => { setExecuting(true) - fetch(globalUrl+"/api/v1/apps/"+appid+"/execute", { + fetch(`${globalUrl}/api/v1/apps/${appid}/execute`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -1148,18 +1151,19 @@ const CodeEditor = (props) => { } { // console.log(value.getCursor()) @@ -1182,13 +1186,14 @@ const CodeEditor = (props) => { // console.log(findIndex(value.getValue())) // highlight_variables(value) }} + extensions={[indentWithTab]} options={{ styleSelectedText: true, + theme: codeTheme, keyMap: 'sublime', - mode: 'python', - lineWrapping: true, - //theme: codeTheme, - // mode: {codelang}, + mode: validation === true ? "json" : "python", + lineWrapping: linewrap, + }} /> @@ -1360,7 +1365,7 @@ const CodeEditor = (props) => { id='expOutput' style={{ whiteSpace: "pre-wrap", - color: "#f85a3e", + color: "#ebdbb2", fontFamily: "monospace", backgroundColor: "#282828", padding: 10, @@ -1369,7 +1374,10 @@ const CodeEditor = (props) => { borderRadius: theme.palette.borderRadius, maxHeight: 500, minHeight: 500, + minWidth: 500, + maxWidth: 500, overflow: "auto", + whiteSpace: "pre-wrap", }} > {expOutput} diff --git a/frontend/src/views/Admin.jsx b/frontend/src/views/Admin.jsx index 82c45147..6468eeae 100644 --- a/frontend/src/views/Admin.jsx +++ b/frontend/src/views/Admin.jsx @@ -3519,6 +3519,7 @@ const Admin = (props) => { const filesView = curTab !== 3 ? null : { const [cystyle] = useState(cytoscapestyle); const [cy, setCy] = React.useState(); + const [toolsApp, setToolsApp] = React.useState({}); const [currentView, setCurrentView] = React.useState(0); const [triggerAuthentication, setTriggerAuthentication] = React.useState({}); const [triggerFolders, setTriggerFolders] = React.useState([]); @@ -1701,11 +1702,12 @@ const AngularWorkflow = (defaultprops) => { return } - // FIXME - handle versions on left bar - //handleAppVersioning(responseJson) - //var tmpapps = [] - //tmpapps = tmpapps.concat(getExtraApps()) - //tmpapps = tmpapps.concat(responseJson) + // Used for e.g. Liquid testing + const foundTools = responseJson.find((app) => app.name === "Shuffle Tools") + if (foundTools !== undefined && foundTools !== null) { + setToolsApp(foundTools) + } + setApps(responseJson); if (isCloud) { @@ -12554,9 +12556,10 @@ const AngularWorkflow = (defaultprops) => { defaultReturn =