#168: Added prototype of Oauth2 handler with example app
This commit is contained in:
@@ -1529,6 +1529,8 @@ class AppBase:
|
||||
#print(globals())
|
||||
print("Running liquid with data of length %d" % len(template))
|
||||
run = Liquid(template, {'mode': 'python'})
|
||||
|
||||
# Can't handle self yet (?)
|
||||
ret = run.render(**globals())
|
||||
return ret
|
||||
#try:
|
||||
@@ -2059,7 +2061,7 @@ class AppBase:
|
||||
|
||||
#json_replacement = tmpitem.replace(actualitem[index][0], replacement, 1)
|
||||
#print("AFTER POST replacement: %s" % json_replacement)
|
||||
#json_replacement = replacement
|
||||
json_replacement = replacement
|
||||
try:
|
||||
json_replacement = json.loads(replacement)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
|
||||
@@ -2,7 +2,7 @@ module shuffle
|
||||
|
||||
go 1.13
|
||||
|
||||
//replace github.com/frikky/shuffle-shared => ../../../../git/shuffle-shared
|
||||
replace github.com/frikky/shuffle-shared => ../../../../git/shuffle-shared
|
||||
|
||||
//replace github.com/frikky/kin-openapi => ../../../../git/kin-openapi
|
||||
|
||||
|
||||
+30
-11
@@ -1552,7 +1552,6 @@ func handleExecution(id string, workflow shuffle.Workflow, request *http.Request
|
||||
}
|
||||
|
||||
workflowExecution.ExecutionVariables = workflow.ExecutionVariables
|
||||
|
||||
if len(workflowExecution.Start) == 0 && len(workflowExecution.Workflow.Start) > 0 {
|
||||
workflowExecution.Start = workflowExecution.Workflow.Start
|
||||
}
|
||||
@@ -1621,20 +1620,40 @@ func handleExecution(id string, workflow shuffle.Workflow, request *http.Request
|
||||
return shuffle.WorkflowExecution{}, fmt.Sprintf("Auth ID %s doesn't exist", action.AuthenticationId), errors.New(fmt.Sprintf("Auth ID %s doesn't exist", action.AuthenticationId))
|
||||
}
|
||||
|
||||
// Rebuild params with the right data. This is to prevent issues on the frontend
|
||||
newParams := []shuffle.WorkflowAppActionParameter{}
|
||||
for _, param := range action.Parameters {
|
||||
if strings.ToLower(curAuth.Type) == "oauth2" {
|
||||
log.Printf("\n\nShould replace auth parameters!!!\n\n")
|
||||
|
||||
for _, authparam := range curAuth.Fields {
|
||||
if param.Name == authparam.Key {
|
||||
param.Value = authparam.Value
|
||||
//log.Printf("Name: %s - value: %s", param.Name, param.Value)
|
||||
//log.Printf("Name: %s - value: %s\n", param.Name, param.Value)
|
||||
break
|
||||
}
|
||||
for _, param := range curAuth.Fields {
|
||||
newParams = append(newParams, shuffle.WorkflowAppActionParameter{
|
||||
Name: param.Key,
|
||||
Value: param.Value,
|
||||
})
|
||||
}
|
||||
|
||||
newParams = append(newParams, param)
|
||||
for _, param := range action.Parameters {
|
||||
log.Printf("Param: %#v", param)
|
||||
if param.Configuration {
|
||||
continue
|
||||
}
|
||||
|
||||
newParams = append(newParams, param)
|
||||
}
|
||||
} else {
|
||||
// Rebuild params with the right data. This is to prevent issues on the frontend
|
||||
for _, param := range action.Parameters {
|
||||
|
||||
for _, authparam := range curAuth.Fields {
|
||||
if param.Name == authparam.Key {
|
||||
param.Value = authparam.Value
|
||||
//log.Printf("Name: %s - value: %s", param.Name, param.Value)
|
||||
//log.Printf("Name: %s - value: %s\n", param.Name, param.Value)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
newParams = append(newParams, param)
|
||||
}
|
||||
}
|
||||
|
||||
action.Parameters = newParams
|
||||
|
||||
@@ -22,6 +22,7 @@ import AdminSetup from "./views/AdminSetup";
|
||||
import Admin from "./views/Admin";
|
||||
import Docs from "./views/Docs";
|
||||
import Introduction from "./views/Introduction";
|
||||
import SetAuthentication from "./views/SetAuthentication";
|
||||
|
||||
import LandingPageNew from "./views/LandingpageNew";
|
||||
import LoginPage from "./views/LoginPage";
|
||||
@@ -125,6 +126,7 @@ const App = (message, props) => {
|
||||
<Route exact path="/docs" render={props => { window.location.pathname = "/docs/about" }} />
|
||||
<Route exact path="/introduction" render={props => <Introduction isLoaded={isLoaded} globalUrl={globalUrl} {...props} />} />
|
||||
<Route exact path="/introduction/:key" render={props => <Introduction isLoaded={isLoaded} globalUrl={globalUrl} {...props} />} />
|
||||
<Route exact path="/set_authentication" render={props => <SetAuthentication userdata={userdata} isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} />
|
||||
<Route exact path="/" render={props => <LoginPage isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} />
|
||||
</div>
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ const useStyles = makeStyles({
|
||||
//)
|
||||
|
||||
const ParsedAction = (props) => {
|
||||
const {workflow, setWorkflow, setAction, setSelectedAction, setUpdate, appActionArguments, selectedApp, workflowExecutions, setSelectedResult, selectedAction, setSelectedApp, setSelectedTrigger, setSelectedEdge, setCurrentView, cy, setAuthenticationModalOpen,setVariablesModalOpen, setCodeModalOpen, selectedNameChange, rightsidebarStyle, showEnvironment, selectedActionEnvironment, environments, setNewSelectedAction, appApiViewStyle, globalUrl, setSelectedActionEnvironment, requiresAuthentication, hideExtraTypes, scrollConfig, setScrollConfig } = props
|
||||
const {workflow, setWorkflow, setAction, setSelectedAction, setUpdate, appActionArguments, selectedApp, workflowExecutions, setSelectedResult, selectedAction, setSelectedApp, setSelectedTrigger, setSelectedEdge, setCurrentView, cy, setAuthenticationModalOpen,setVariablesModalOpen, setCodeModalOpen, selectedNameChange, rightsidebarStyle, showEnvironment, selectedActionEnvironment, environments, setNewSelectedAction, appApiViewStyle, globalUrl, setSelectedActionEnvironment, requiresAuthentication, hideExtraTypes, scrollConfig, setScrollConfig, authenticationType, appAuthentication, getAppAuthentication } = props
|
||||
|
||||
const theme = useTheme();
|
||||
const classes = useStyles()
|
||||
@@ -1389,6 +1389,42 @@ const ParsedAction = (props) => {
|
||||
<Tooltip color="primary" title={"Add authentication option"} placement="top">
|
||||
<span>
|
||||
<Button color="primary" style={{}} fullWidth variant="contained" onClick={() => {
|
||||
console.log(authenticationType)
|
||||
if (authenticationType.type === "oauth2" && authenticationType.redirect_uri !== undefined && authenticationType.redirect_uri !== null) {
|
||||
// FIXME: Sending client secret and senitive info like this may not be ok.
|
||||
const client_id = "dae24316-4bec-4832-b660-4cba6dc2477b"
|
||||
const client_secret = "._Qu3EvYY-OW_D57uy79qwEo.32qD6.l0z"
|
||||
const authentication_url = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
|
||||
const resources = "UserAuthenticationMethod.ReadWrite.All"
|
||||
|
||||
const redirectUri = `http://${window.location.host}/set_authentication`
|
||||
const state = `workflow_id%3D${workflow.id}%26reference_action_id%3d${selectedAction.app_id}%26app_name%3d${selectedAction.app_name}%26app_id%3d${selectedAction.app_id}%26app_version%3d${selectedAction.app_version}%26authentication_url%3d${authentication_url}%26scope%3d${resources}%26client_id%3d${client_id}%26client_secret%3d${client_secret}`
|
||||
|
||||
const url = `https://login.microsoftonline.com/common/oauth2/authorize?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&scope=${resources}&state=${state}`
|
||||
// &resource=https%3A%2F%2Fgraph.microsoft.com&
|
||||
|
||||
var newwin = window.open(url, "", "width=200,height=100")
|
||||
console.log(newwin)
|
||||
setTimeout(() => {
|
||||
console.log(newwin)
|
||||
console.log("CLOSED", newwin.closed)
|
||||
}, 1000)
|
||||
setTimeout(() => {
|
||||
console.log(newwin)
|
||||
console.log("CLOSED", newwin.closed)
|
||||
if (newwin.closed) {
|
||||
getAppAuthentication(true)
|
||||
setTimeout(() => {
|
||||
console.log("APPAUTH: ", appAuthentication)
|
||||
}, 1500)
|
||||
}
|
||||
}, 10000)
|
||||
|
||||
return
|
||||
//do {
|
||||
//} while (
|
||||
}
|
||||
|
||||
setAuthenticationModalOpen(true)
|
||||
}}>
|
||||
<AddIcon style={{marginRight: 10, }}/> Authenticate {selectedApp.name}
|
||||
|
||||
@@ -171,6 +171,7 @@ const AngularWorkflow = (props) => {
|
||||
const [authenticationModalOpen, setAuthenticationModalOpen] = React.useState(false);
|
||||
const [conditionsModalOpen, setConditionsModalOpen] = React.useState(false);
|
||||
const [newVariableName, setNewVariableName] = React.useState("");
|
||||
const [authenticationType, setAuthenticationType] = React.useState("");
|
||||
const [newVariableDescription, setNewVariableDescription] = React.useState("");
|
||||
const [newVariableValue, setNewVariableValue] = React.useState("");
|
||||
const [workflowDone, setWorkflowDone] = React.useState(false)
|
||||
@@ -1944,9 +1945,19 @@ const AngularWorkflow = (props) => {
|
||||
setSelectedAction(curaction)
|
||||
//return
|
||||
} else {
|
||||
console.log("AUTHENTICATION: ", curapp.authentication)
|
||||
setAuthenticationType(curapp.authentication.type === "oauth2" && curapp.authentication.redirect_uri !== undefined && curapp.authentication.redirect_uri !== null ?
|
||||
{
|
||||
"type": "oauth2",
|
||||
"redirect_uri": curapp.authentication.redirect_uri,
|
||||
} : {
|
||||
"type": ""
|
||||
}
|
||||
)
|
||||
|
||||
//console.log("AUTHENTICATION: ", curapp.authentication)
|
||||
setRequiresAuthentication(curapp.authentication.required && curapp.authentication.parameters !== undefined && curapp.authentication.parameters !== null)
|
||||
const requiresAuth = curapp.authentication.required //&& ((curapp.authentication.parameters !== undefined && curapp.authentication.parameters !== null) || (curapp.authentication.type === "oauth2" && curapp.authentication.redirect_uri !== undefined && curapp.authentication.redirect_uri !== null))
|
||||
console.log("AUTHCHECK: ", requiresAuth)
|
||||
setRequiresAuthentication(requiresAuth)
|
||||
if (curapp.authentication.required) {
|
||||
//console.log("App requires auth.")
|
||||
// Setup auth here :)
|
||||
@@ -7431,6 +7442,9 @@ const AngularWorkflow = (props) => {
|
||||
<div id="rightside_actions" style={rightsidebarStyle}>
|
||||
<ParsedAction
|
||||
id="rightside_subactions"
|
||||
getAppAuthentication={getAppAuthentication}
|
||||
appAuthentication={appAuthentication}
|
||||
authenticationType={authenticationType}
|
||||
scrollConfig={scrollConfig}
|
||||
setScrollConfig={setScrollConfig}
|
||||
selectedAction={selectedAction}
|
||||
@@ -8138,7 +8152,7 @@ const AngularWorkflow = (props) => {
|
||||
// //cf80fa70-65cf-4963-b474-b459a6dead81
|
||||
//}
|
||||
|
||||
console.log(selectedResult)
|
||||
//console.log(selectedResult)
|
||||
const codePopoutModal = !codeModalOpen ? null :
|
||||
<Draggable
|
||||
onDrag={(e) => {
|
||||
@@ -8709,10 +8723,11 @@ const AngularWorkflow = (props) => {
|
||||
authenticationOption.label = selectedApp.name+" authentication"
|
||||
}
|
||||
|
||||
//console.log(
|
||||
return (
|
||||
<div>
|
||||
<DialogContent>
|
||||
<a target="_blank" rel="norefferer" href="https://shuffler.io/docs/apps#authentication" style={{textDecoration: "none", color: "#f85a3e"}}>What is this?</a><div/>
|
||||
<a target="_blank" rel="norefferer" href="https://shuffler.io/docs/apps#authentication" style={{textDecoration: "none", color: "#f85a3e"}}>What is app authentication?</a><div/>
|
||||
These are required fields for authenticating with {selectedApp.name}
|
||||
<div style={{marginTop: 15}}/>
|
||||
<b>Name - what is this used for?</b>
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
import React, {useRef, useState, useEffect, useLayoutEffect} from 'react';
|
||||
|
||||
import { Typography, CircularProgress } from '@material-ui/core';
|
||||
|
||||
const SetAuthentication = (props) => {
|
||||
const { globalUrl, isLoggedIn, isLoaded, userdata } = props;
|
||||
|
||||
const [firstRequest, setFirstRequest] = useState(true)
|
||||
const [finished, setFinished] = useState(false)
|
||||
const [response, setResponse] = useState("")
|
||||
const [failed, setFailed] = useState(false)
|
||||
|
||||
if (firstRequest) {
|
||||
setFirstRequest(false)
|
||||
|
||||
//code
|
||||
//session_state
|
||||
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||
const params = Object.fromEntries(urlSearchParams.entries());
|
||||
|
||||
const authenticationStore = []
|
||||
var appAuthData = {
|
||||
"label": "",
|
||||
"app": {
|
||||
"name": "",
|
||||
"id": "",
|
||||
"app_version": "",
|
||||
},
|
||||
"fields": [],
|
||||
"type": "oauth2",
|
||||
}
|
||||
|
||||
if (window !== undefined && window !== null) {
|
||||
console.log(window.location)
|
||||
appAuthData.fields.push({"key": "redirect_uri", "value": window.location.origin+window.location.pathname})
|
||||
}
|
||||
|
||||
if (params.code !== undefined && params.code !== null) {
|
||||
appAuthData.fields.push({"key": "code", "value": params.code})
|
||||
}
|
||||
|
||||
if (params.session_state !== undefined && params.session_state !== null) {
|
||||
appAuthData.fields.push({"key": "session_state", "value": params.session_state})
|
||||
}
|
||||
|
||||
if (params.state !== undefined && params.state !== null) {
|
||||
const paramsplit = params.state.split("&")
|
||||
console.log(paramsplit)
|
||||
for (var key in paramsplit) {
|
||||
const query = paramsplit[key].split("=")
|
||||
console.log(query)
|
||||
|
||||
if (query.length !== 2) {
|
||||
console.log("INVALID QUERY: ", query)
|
||||
continue
|
||||
}
|
||||
|
||||
if (query[0] === "workflow_id") {
|
||||
appAuthData.reference_workflow = query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "reference_action_id") {
|
||||
//appAuthData.ReferenceWorkflow = query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "app_name") {
|
||||
appAuthData.app.name = query[1]
|
||||
appAuthData.label = "Oauth2 for "+query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "app_id") {
|
||||
appAuthData.app.id = query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "app_version") {
|
||||
appAuthData.app.app_version = query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "authentication_url") {
|
||||
appAuthData.fields.push({"key": "authentication_url", "value": query[1]})
|
||||
}
|
||||
|
||||
if (query[0] === "scope") {
|
||||
appAuthData.fields.push({"key": "scope", "value": query[1]})
|
||||
}
|
||||
|
||||
if (query[0] === "client_id") {
|
||||
appAuthData.fields.push({"key": "client_id", "value": query[1]})
|
||||
}
|
||||
|
||||
if (query[0] === "client_secret") {
|
||||
appAuthData.fields.push({"key": "client_secret", "value": query[1]})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(appAuthData)
|
||||
|
||||
fetch(globalUrl+"/api/v1/apps/authentication", {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: "include",
|
||||
body: JSON.stringify(appAuthData),
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for oauth2 authentication")
|
||||
setFailed(true)
|
||||
}
|
||||
|
||||
return response.json()
|
||||
})
|
||||
.then((responseJson) => {
|
||||
//setUserSettings(responseJson)
|
||||
console.log("Resp: ", responseJson)
|
||||
setFinished(true)
|
||||
setResponse(responseJson.reason)
|
||||
|
||||
setTimeout(() => {
|
||||
window.close()
|
||||
}, 1000)
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{width: 1000, margin: "auto", itemAlign: "center",}}>
|
||||
<Typography variant="h6" style={{marginLeft: "auto", marginRight: "auto", marginTop: 200, }}>
|
||||
{!finished ? <CircularProgress /> : "DONE WITH AUTH - this will close soon!!"}
|
||||
<div />
|
||||
{failed ? "Failed setup. Error: " : ""} {response}
|
||||
</Typography>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SetAuthentication;
|
||||
@@ -1958,7 +1958,6 @@ func downloadDockerImageBackend(client *http.Client, imageName string) error {
|
||||
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", authorization))
|
||||
} else {
|
||||
log.Printf("[WARNING] No auth found - running backend download without it.")
|
||||
//req.Header.Add("Authorization", fmt.Sprintf("Bearer db0373c6-1083-4dec-a05d-3ba73f02ccd4"))
|
||||
//return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user