Skip to content

Commit ae93d49

Browse files
committed
add support for bearer token auth type
1 parent 7cc718a commit ae93d49

7 files changed

Lines changed: 188 additions & 94 deletions

File tree

packages/flowtest-cli/graph/compute/authnode.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ class authNode extends Node {
2323
username,
2424
password,
2525
};
26+
} else if (this.nodeData.type === 'bearer-token') {
27+
this.logger.add(LogLevel.INFO, '', { type: 'authNode', data: { authType: 'Bearer Token' } });
28+
const token = computeVariables(this.nodeData.token, this.envVariables);
29+
return {
30+
type: 'bearer-token',
31+
token,
32+
};
2633
} else if (this.nodeData.type === 'no-auth') {
2734
console.log(chalk.green(` ✓ `) + chalk.dim('.....using no authentication'));
2835
this.logger.add(LogLevel.INFO, '', { type: 'authNode', data: { authType: 'No Authentication' } });

packages/flowtest-cli/graph/compute/requestnode.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,18 @@ class requestNode extends Node {
123123
});
124124
}
125125

126+
if (this.auth && this.auth?.type === 'bearer-token') {
127+
headers['Authorization'] = `Bearer ${this.auth.token}`;
128+
}
129+
126130
const options = {
127131
method: restMethod,
128132
url: finalUrl,
129133
headers,
130134
data: requestData,
131135
};
132136

133-
if (this.auth && this.auth.type === 'basic-auth') {
137+
if (this.auth && this.auth?.type === 'basic-auth') {
134138
options.auth = {};
135139
options.auth.username = this.auth.username;
136140
options.auth.password = this.auth.password;

src/components/molecules/flow/graph/compute/authnode.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ class authNode extends Node {
2121
username,
2222
password,
2323
};
24+
} else if (this.nodeData.type === 'bearer-token') {
25+
this.logger.add(LogLevel.INFO, '', { type: 'authNode', data: { authType: 'Bearer Token' } });
26+
const token = computeVariables(this.nodeData.token, this.envVariables);
27+
return {
28+
type: 'bearer-token',
29+
token,
30+
};
2431
} else if (this.nodeData.type === 'no-auth') {
2532
this.logger.add(LogLevel.INFO, '', { type: 'authNode', data: { authType: 'No Authentication' } });
2633
return {

src/components/molecules/flow/graph/compute/requestnode.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ class requestNode extends Node {
103103
});
104104
}
105105

106+
if (this.auth && this.auth?.type === 'bearer-token') {
107+
headers['Authorization'] = `Bearer ${this.auth.token}`;
108+
}
109+
106110
const options = {
107111
method: restMethod,
108112
url: finalUrl,

src/components/molecules/flow/nodes/AuthNode.js

Lines changed: 133 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,17 @@ import { cloneDeep } from 'lodash';
1313
const AuthNode = ({ id, data }) => {
1414
const setAuthNodeType = useCanvasStore((state) => state.setAuthNodeType);
1515
const setBasicAuthValues = useCanvasStore((state) => state.setBasicAuthValues);
16-
const [selected, setSelected] = useState(data.type && data.type === 'basic-auth' ? 'basic-auth' : 'no-auth');
16+
const setBearerTokenValue = useCanvasStore((state) => state.setBearerTokenValue);
17+
const [selected, setSelected] = useState(data.type ? data.type : 'no-auth');
1718

18-
const handleChange = (value, option) => {
19+
const handleBasicAuthValueChange = (value, option) => {
1920
setBasicAuthValues(id, option, value);
2021
};
2122

23+
const handleBearerTokenChange = (value) => {
24+
setBearerTokenValue(id, value);
25+
};
26+
2227
const getActiveVariables = () => {
2328
const collectionId = useCanvasStore.getState().collectionId;
2429
if (collectionId) {
@@ -33,6 +38,16 @@ const AuthNode = ({ id, data }) => {
3338
return [];
3439
};
3540

41+
const getAuthType = () => {
42+
if (selected === 'no-auth') {
43+
return 'No Auth';
44+
} else if (selected === 'basic-auth') {
45+
return 'Basic Auth';
46+
} else if (selected === 'bearer-token') {
47+
return 'Bearer Token';
48+
}
49+
};
50+
3651
return (
3752
<>
3853
<FlowNode
@@ -42,89 +57,122 @@ const AuthNode = ({ id, data }) => {
4257
handleRight={true}
4358
handleRightData={{ type: 'source' }}
4459
>
45-
<Listbox
46-
value={selected}
47-
onChange={(selectedValue) => {
48-
setSelected(selectedValue);
49-
setAuthNodeType(id, selectedValue);
50-
}}
51-
>
52-
<div className='relative min-w-36'>
53-
<Listbox.Button className='relative w-full p-2 text-left border rounded cursor-default border-cyan-950'>
54-
<span className='block truncate'>{selected === 'no-auth' ? 'No Auth' : 'Basic Auth'}</span>
55-
<span className='absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none'>
56-
<ChevronUpDownIcon className='w-5 h-5' aria-hidden='true' />
57-
</span>
58-
</Listbox.Button>
59-
<Transition
60-
as={Fragment}
61-
leave='transition ease-in duration-100'
62-
leaveFrom='opacity-100'
63-
leaveTo='opacity-0'
64-
>
65-
<Listbox.Options className='absolute z-10 w-full py-1 mt-1 overflow-auto text-base bg-white max-h-60 focus:outline-none'>
66-
<Listbox.Option
67-
className={({ active }) =>
68-
`relative cursor-default select-none py-2 pl-10 pr-4 hover:font-semibold ${
69-
active ? 'bg-background-light text-slate-900' : ''
70-
}`
71-
}
72-
value={'no-auth'}
73-
>
74-
{({ selected }) => (
75-
<>
76-
<span className={`block`}>No Auth</span>
77-
{selected ? (
78-
<span className='absolute inset-y-0 left-0 flex items-center pl-3 font-semibold'>
79-
<CheckIcon className='w-5 h-5' aria-hidden='true' />
80-
</span>
81-
) : null}
82-
</>
83-
)}
84-
</Listbox.Option>
85-
<Listbox.Option
86-
className={({ active }) =>
87-
`relative cursor-default select-none py-2 pl-10 pr-4 hover:font-semibold ${
88-
active ? 'bg-background-light text-slate-900' : ''
89-
}`
90-
}
91-
value={'basic-auth'}
92-
>
93-
{({ selected }) => (
94-
<>
95-
<span className={`block`}>Basic auth</span>
96-
{selected ? (
97-
<span className='absolute inset-y-0 left-0 flex items-center pl-3 font-semibold'>
98-
<CheckIcon className='w-5 h-5' aria-hidden='true' />
99-
</span>
100-
) : null}
101-
</>
102-
)}
103-
</Listbox.Option>
104-
</Listbox.Options>
105-
</Transition>
106-
</div>
107-
</Listbox>
108-
{data.type === 'basic-auth' && (
109-
<div className='flex flex-col gap-2 py-4'>
110-
<TextEditor
111-
placeHolder={`Username`}
112-
onChangeHandler={(value) => handleChange(value, 'username')}
113-
name={'username'}
114-
value={data.username ? data.username : ''}
115-
completionOptions={getActiveVariables()}
116-
styles={'w-full'}
117-
/>
118-
<TextEditor
119-
placeHolder={`Password`}
120-
onChangeHandler={(value) => handleChange(value, 'password')}
121-
name={'password'}
122-
value={data.password ? data.password : ''}
123-
completionOptions={getActiveVariables()}
124-
styles={'w-full'}
125-
/>
126-
</div>
127-
)}
60+
<div className='w-52'>
61+
<Listbox
62+
value={selected}
63+
onChange={(selectedValue) => {
64+
setSelected(selectedValue);
65+
setAuthNodeType(id, selectedValue);
66+
}}
67+
>
68+
<div className='relative'>
69+
<Listbox.Button className='relative w-full cursor-default rounded border border-cyan-950 p-2 text-left'>
70+
<span className='block truncate'>{getAuthType()}</span>
71+
<span className='pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2'>
72+
<ChevronUpDownIcon className='h-5 w-5' aria-hidden='true' />
73+
</span>
74+
</Listbox.Button>
75+
<Transition
76+
as={Fragment}
77+
leave='transition ease-in duration-100'
78+
leaveFrom='opacity-100'
79+
leaveTo='opacity-0'
80+
>
81+
<Listbox.Options className='absolute z-10 mt-1 max-h-60 w-full overflow-auto bg-white py-1 text-base focus:outline-none'>
82+
<Listbox.Option
83+
className={({ active }) =>
84+
`relative cursor-default select-none py-2 pl-10 pr-4 hover:font-semibold ${
85+
active ? 'bg-background-light text-slate-900' : ''
86+
}`
87+
}
88+
value={'no-auth'}
89+
>
90+
{({ selected }) => (
91+
<>
92+
<span className={`block`}>No Auth</span>
93+
{selected ? (
94+
<span className='absolute inset-y-0 left-0 flex items-center pl-3 font-semibold'>
95+
<CheckIcon className='h-5 w-5' aria-hidden='true' />
96+
</span>
97+
) : null}
98+
</>
99+
)}
100+
</Listbox.Option>
101+
<Listbox.Option
102+
className={({ active }) =>
103+
`relative cursor-default select-none py-2 pl-10 pr-4 hover:font-semibold ${
104+
active ? 'bg-background-light text-slate-900' : ''
105+
}`
106+
}
107+
value={'basic-auth'}
108+
>
109+
{({ selected }) => (
110+
<>
111+
<span className={`block`}>Basic auth</span>
112+
{selected ? (
113+
<span className='absolute inset-y-0 left-0 flex items-center pl-3 font-semibold'>
114+
<CheckIcon className='h-5 w-5' aria-hidden='true' />
115+
</span>
116+
) : null}
117+
</>
118+
)}
119+
</Listbox.Option>
120+
<Listbox.Option
121+
className={({ active }) =>
122+
`relative cursor-default select-none py-2 pl-10 pr-4 hover:font-semibold ${
123+
active ? 'bg-background-light text-slate-900' : ''
124+
}`
125+
}
126+
value={'bearer-token'}
127+
>
128+
{({ selected }) => (
129+
<>
130+
<span className={`block`}>Bearer Token</span>
131+
{selected ? (
132+
<span className='absolute inset-y-0 left-0 flex items-center pl-3 font-semibold'>
133+
<CheckIcon className='h-5 w-5' aria-hidden='true' />
134+
</span>
135+
) : null}
136+
</>
137+
)}
138+
</Listbox.Option>
139+
</Listbox.Options>
140+
</Transition>
141+
</div>
142+
</Listbox>
143+
{data.type === 'basic-auth' && (
144+
<div className='flex flex-col gap-2 py-4'>
145+
<TextEditor
146+
placeHolder={`Username`}
147+
onChangeHandler={(value) => handleBasicAuthValueChange(value, 'username')}
148+
name={'username'}
149+
value={data.username ? data.username : ''}
150+
completionOptions={getActiveVariables()}
151+
styles={'w-full'}
152+
/>
153+
<TextEditor
154+
placeHolder={`Password`}
155+
onChangeHandler={(value) => handleBasicAuthValueChange(value, 'password')}
156+
name={'password'}
157+
value={data.password ? data.password : ''}
158+
completionOptions={getActiveVariables()}
159+
styles={'w-full'}
160+
/>
161+
</div>
162+
)}
163+
{data.type === 'bearer-token' && (
164+
<div className='flex flex-col gap-2 py-4'>
165+
<TextEditor
166+
placeHolder={`Token`}
167+
onChangeHandler={(value) => handleBearerTokenChange(value)}
168+
name={'token'}
169+
value={data.token ? data.token : ''}
170+
completionOptions={getActiveVariables()}
171+
styles={'w-full'}
172+
/>
173+
</div>
174+
)}
175+
</div>
128176
</FlowNode>
129177
</>
130178
);

src/components/molecules/flow/nodes/RequestNode.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -324,27 +324,24 @@ const RequestNode = ({ id, data }) => {
324324
/>
325325
<NodeHorizontalDivider />
326326
<Tab.Group defaultIndex={getDefaultIndex()}>
327-
<Tab.List className='flex space-x-1 rounded-xl bg-blue-900/20 p-1'>
327+
<Tab.List className='flex'>
328328
<Tab
329329
className={({ selected }) =>
330-
`w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-blue-700
331-
${selected ? 'bg-white shadow' : 'text-blue-100 hover:bg-white/[0.12] hover:text-white'}`
330+
`w-full p-2 ${selected ? 'rounded border border-cyan-900 bg-slate-100' : ''}`
332331
}
333332
>
334333
Body
335334
</Tab>
336335
<Tab
337336
className={({ selected }) =>
338-
`w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-blue-700
339-
${selected ? 'bg-white shadow' : 'text-blue-100 hover:bg-white/[0.12] hover:text-white'}`
337+
`w-full p-2 ${selected ? 'rounded border border-cyan-900 bg-slate-100' : ''}`
340338
}
341339
>
342340
Variables
343341
</Tab>
344342
<Tab
345343
className={({ selected }) =>
346-
`w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-blue-700
347-
${selected ? 'bg-white shadow' : 'text-blue-100 hover:bg-white/[0.12] hover:text-white'}`
344+
`w-full p-2 ${selected ? 'rounded border border-cyan-900 bg-slate-100' : ''}`
348345
}
349346
>
350347
Headers

src/stores/CanvasStore.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ const useCanvasStore = create((set, get) => ({
6565
type: authType,
6666
},
6767
};
68-
} else {
68+
} else if (authType == 'basic-auth') {
6969
return {
7070
...node,
7171
data: {
@@ -74,6 +74,14 @@ const useCanvasStore = create((set, get) => ({
7474
password: '',
7575
},
7676
};
77+
} else if (authType == 'bearer-token') {
78+
return {
79+
...node,
80+
data: {
81+
type: authType,
82+
token: '',
83+
},
84+
};
7785
}
7886
}
7987

@@ -101,6 +109,25 @@ const useCanvasStore = create((set, get) => ({
101109
});
102110
useTabStore.getState().updateFlowTestNodes(useTabStore.getState().focusTabId, get().nodes);
103111
},
112+
setBearerTokenValue: (nodeId, token) => {
113+
set({
114+
nodes: get().nodes.map((node) => {
115+
if (node.id === nodeId) {
116+
// it's important to create a new object here, to inform React Flow about the cahnges
117+
return {
118+
...node,
119+
data: {
120+
...node.data,
121+
token,
122+
},
123+
};
124+
}
125+
126+
return node;
127+
}),
128+
});
129+
useTabStore.getState().updateFlowTestNodes(useTabStore.getState().focusTabId, get().nodes);
130+
},
104131
setRequestNodeType: (nodeId, requestType) => {
105132
set({
106133
nodes: get().nodes.map((node) => {

0 commit comments

Comments
 (0)