Skip to content

Commit 3421a3d

Browse files
Mateusz Pietrygapietrygamat
Mateusz Pietryga
authored andcommitted
OAuth2: Implement OAuth 2.0 Implicit Grant
usebruno#2056
1 parent fc62604 commit 3421a3d

File tree

21 files changed

+519
-41
lines changed

21 files changed

+519
-41
lines changed

Diff for: packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/GrantTypeSelector/index.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ import Dropdown from 'components/Dropdown';
44
import { useDispatch } from 'react-redux';
55
import StyledWrapper from './StyledWrapper';
66
import { IconCaretDown } from '@tabler/icons';
7-
import { updateAuth } from 'providers/ReduxStore/slices/collections';
87
import { humanizeGrantType } from 'utils/collections';
98
import { useEffect } from 'react';
10-
import { updateCollectionAuth, updateCollectionAuthMode } from 'providers/ReduxStore/slices/collections/index';
9+
import { updateCollectionAuth, updateCollectionAuthMode } from 'providers/ReduxStore/slices/collections';
1110

1211
const GrantTypeSelector = ({ collection }) => {
1312
const dispatch = useDispatch();
@@ -90,6 +89,15 @@ const GrantTypeSelector = ({ collection }) => {
9089
>
9190
Client Credentials
9291
</div>
92+
<div
93+
className="dropdown-item"
94+
onClick={() => {
95+
dropdownTippyRef.current.hide();
96+
onGrantTypeChange('implicit');
97+
}}
98+
>
99+
Implicit
100+
</div>
93101
</Dropdown>
94102
</div>
95103
</StyledWrapper>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import styled from 'styled-components';
2+
3+
const Wrapper = styled.div`
4+
label {
5+
font-size: 0.8125rem;
6+
}
7+
.single-line-editor-wrapper {
8+
max-width: 400px;
9+
padding: 0.15rem 0.4rem;
10+
border-radius: 3px;
11+
border: solid 1px ${(props) => props.theme.input.border};
12+
background-color: ${(props) => props.theme.input.bg};
13+
}
14+
`;
15+
16+
export default Wrapper;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import React from 'react';
2+
import get from 'lodash/get';
3+
import { useTheme } from 'providers/Theme';
4+
import { useDispatch } from 'react-redux';
5+
import SingleLineEditor from 'components/SingleLineEditor';
6+
import { saveCollectionRoot, sendCollectionOauth2Request } from 'providers/ReduxStore/slices/collections/actions';
7+
import StyledWrapper from './StyledWrapper';
8+
import { inputsConfig } from './inputsConfig';
9+
import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections';
10+
import { clearOauth2Cache } from 'utils/network';
11+
import toast from 'react-hot-toast';
12+
13+
const OAuth2Implicit = ({ collection }) => {
14+
const dispatch = useDispatch();
15+
const { storedTheme } = useTheme();
16+
17+
const oAuth = get(collection, 'root.request.auth.oauth2', {});
18+
19+
const handleRun = async () => {
20+
dispatch(sendCollectionOauth2Request(collection.uid));
21+
};
22+
23+
const handleSave = () => dispatch(saveCollectionRoot(collection.uid));
24+
25+
const { callbackUrl, authorizationUrl, clientId, scope, state } = oAuth;
26+
27+
const handleChange = (key, value) => {
28+
dispatch(
29+
updateCollectionAuth({
30+
mode: 'oauth2',
31+
collectionUid: collection.uid,
32+
content: {
33+
grantType: 'implicit',
34+
callbackUrl,
35+
authorizationUrl,
36+
clientId,
37+
scope,
38+
state,
39+
[key]: value
40+
}
41+
})
42+
);
43+
};
44+
45+
const handleClearCache = (e) => {
46+
clearOauth2Cache(collection?.uid)
47+
.then(() => {
48+
toast.success('cleared cache successfully');
49+
})
50+
.catch((err) => {
51+
toast.error(err.message);
52+
});
53+
};
54+
55+
return (
56+
<StyledWrapper className="mt-2 flex w-full gap-4 flex-col">
57+
{inputsConfig.map((input) => {
58+
const { key, label } = input;
59+
return (
60+
<div className="flex flex-col w-full gap-1" key={`input-${key}`}>
61+
<label className="block font-medium">{label}</label>
62+
<div className="single-line-editor-wrapper">
63+
<SingleLineEditor
64+
value={oAuth[key] || ''}
65+
theme={storedTheme}
66+
onSave={handleSave}
67+
onChange={(val) => handleChange(key, val)}
68+
onRun={handleRun}
69+
collection={collection}
70+
/>
71+
</div>
72+
</div>
73+
);
74+
})}
75+
<div className="flex flex-row gap-4">
76+
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
77+
Get Access Token
78+
</button>
79+
<button onClick={handleClearCache} className="submit btn btn-sm btn-secondary w-fit">
80+
Clear Cache
81+
</button>
82+
</div>
83+
</StyledWrapper>
84+
);
85+
};
86+
87+
export default OAuth2Implicit;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const inputsConfig = [
2+
{
3+
key: 'callbackUrl',
4+
label: 'Callback URL'
5+
},
6+
{
7+
key: 'authorizationUrl',
8+
label: 'Authorization URL'
9+
},
10+
{
11+
key: 'clientId',
12+
label: 'Client ID'
13+
},
14+
{
15+
key: 'scope',
16+
label: 'Scope'
17+
},
18+
{
19+
key: 'state',
20+
label: 'State'
21+
}
22+
];
23+
24+
export { inputsConfig };

Diff for: packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/index.js

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import GrantTypeSelector from './GrantTypeSelector/index';
55
import OAuth2PasswordCredentials from './PasswordCredentials/index';
66
import OAuth2AuthorizationCode from './AuthorizationCode/index';
77
import OAuth2ClientCredentials from './ClientCredentials/index';
8+
import OAuth2Implicit from './Implicit/index';
89

910
const grantTypeComponentMap = (grantType, collection) => {
1011
switch (grantType) {
@@ -17,6 +18,9 @@ const grantTypeComponentMap = (grantType, collection) => {
1718
case 'client_credentials':
1819
return <OAuth2ClientCredentials collection={collection} />;
1920
break;
21+
case 'implicit':
22+
return <OAuth2Implicit collection={collection} />;
23+
break;
2024
default:
2125
return <div>TBD</div>;
2226
break;

Diff for: packages/bruno-app/src/components/RequestPane/Auth/OAuth2/GrantTypeSelector/index.js

+9
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ const GrantTypeSelector = ({ item, collection }) => {
8484
>
8585
Client Credentials
8686
</div>
87+
<div
88+
className="dropdown-item"
89+
onClick={() => {
90+
dropdownTippyRef.current.hide();
91+
onGrantTypeChange('implicit');
92+
}}
93+
>
94+
Implicit
95+
</div>
8796
</Dropdown>
8897
</div>
8998
</StyledWrapper>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import styled from 'styled-components';
2+
3+
const Wrapper = styled.div`
4+
label {
5+
font-size: 0.8125rem;
6+
}
7+
.single-line-editor-wrapper {
8+
max-width: 400px;
9+
padding: 0.15rem 0.4rem;
10+
border-radius: 3px;
11+
border: solid 1px ${(props) => props.theme.input.border};
12+
background-color: ${(props) => props.theme.input.bg};
13+
}
14+
`;
15+
16+
export default Wrapper;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import React from 'react';
2+
import get from 'lodash/get';
3+
import { useTheme } from 'providers/Theme';
4+
import { useDispatch } from 'react-redux';
5+
import SingleLineEditor from 'components/SingleLineEditor';
6+
import { updateAuth } from 'providers/ReduxStore/slices/collections';
7+
import { saveRequest, sendRequest } from 'providers/ReduxStore/slices/collections/actions';
8+
import StyledWrapper from './StyledWrapper';
9+
import { inputsConfig } from './inputsConfig';
10+
import { clearOauth2Cache } from 'utils/network';
11+
import toast from 'react-hot-toast';
12+
13+
const OAuth2Implicit = ({ item, collection }) => {
14+
const dispatch = useDispatch();
15+
const { storedTheme } = useTheme();
16+
17+
const oAuth = item.draft ? get(item, 'draft.request.auth.oauth2', {}) : get(item, 'request.auth.oauth2', {});
18+
19+
const handleRun = async () => {
20+
dispatch(sendRequest(item, collection.uid));
21+
};
22+
23+
const handleSave = () => dispatch(saveRequest(item.uid, collection.uid));
24+
25+
const { callbackUrl, authorizationUrl, clientId, scope, state } = oAuth;
26+
27+
const handleChange = (key, value) => {
28+
dispatch(
29+
updateAuth({
30+
mode: 'oauth2',
31+
collectionUid: collection.uid,
32+
itemUid: item.uid,
33+
content: {
34+
grantType: 'implicit',
35+
callbackUrl,
36+
authorizationUrl,
37+
clientId,
38+
scope,
39+
state,
40+
[key]: value
41+
}
42+
})
43+
);
44+
};
45+
46+
const handleClearCache = (e) => {
47+
clearOauth2Cache(collection?.uid)
48+
.then(() => {
49+
toast.success('cleared cache successfully');
50+
})
51+
.catch((err) => {
52+
toast.error(err.message);
53+
});
54+
};
55+
56+
return (
57+
<StyledWrapper className="mt-2 flex w-full gap-4 flex-col">
58+
{inputsConfig.map((input) => {
59+
const { key, label } = input;
60+
return (
61+
<div className="flex flex-col w-full gap-1" key={`input-${key}`}>
62+
<label className="block font-medium">{label}</label>
63+
<div className="single-line-editor-wrapper">
64+
<SingleLineEditor
65+
value={oAuth[key] || ''}
66+
theme={storedTheme}
67+
onSave={handleSave}
68+
onChange={(val) => handleChange(key, val)}
69+
onRun={handleRun}
70+
collection={collection}
71+
/>
72+
</div>
73+
</div>
74+
);
75+
})}
76+
<div className="flex flex-row gap-4">
77+
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
78+
Get Access Token
79+
</button>
80+
<button onClick={handleClearCache} className="submit btn btn-sm btn-secondary w-fit">
81+
Clear Cache
82+
</button>
83+
</div>
84+
</StyledWrapper>
85+
);
86+
};
87+
88+
export default OAuth2Implicit;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const inputsConfig = [
2+
{
3+
key: 'callbackUrl',
4+
label: 'Callback URL'
5+
},
6+
{
7+
key: 'authorizationUrl',
8+
label: 'Authorization URL'
9+
},
10+
{
11+
key: 'clientId',
12+
label: 'Client ID'
13+
},
14+
{
15+
key: 'scope',
16+
label: 'Scope'
17+
},
18+
{
19+
key: 'state',
20+
label: 'State'
21+
}
22+
];
23+
24+
export { inputsConfig };

Diff for: packages/bruno-app/src/components/RequestPane/Auth/OAuth2/index.js

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import GrantTypeSelector from './GrantTypeSelector/index';
55
import OAuth2PasswordCredentials from './PasswordCredentials/index';
66
import OAuth2AuthorizationCode from './AuthorizationCode/index';
77
import OAuth2ClientCredentials from './ClientCredentials/index';
8+
import OAuth2Implicit from './Implicit/index';
89

910
const grantTypeComponentMap = (grantType, item, collection) => {
1011
switch (grantType) {
@@ -17,6 +18,9 @@ const grantTypeComponentMap = (grantType, item, collection) => {
1718
case 'client_credentials':
1819
return <OAuth2ClientCredentials item={item} collection={collection} />;
1920
break;
21+
case 'implicit':
22+
return <OAuth2Implicit item={item} collection={collection} />;
23+
break;
2024
default:
2125
return <div>TBD</div>;
2226
break;

Diff for: packages/bruno-app/src/utils/collections/index.js

+4
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,10 @@ export const humanizeGrantType = (mode) => {
577577
label = 'Client Credentials';
578578
break;
579579
}
580+
case 'implicit': {
581+
label = 'Implicit';
582+
break;
583+
}
580584
}
581585

582586
return label;

0 commit comments

Comments
 (0)