Skip to content

feat: extend support for more auth in folder level #4609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ const Wrapper = styled.div`
border: solid 1px ${(props) => props.theme.input.border};
background-color: ${(props) => props.theme.input.bg};
}
.inherit-mode-text {
color: ${(props) => props.theme.colors.text.yellow};
}
.auth-mode-label {
color: ${(props) => props.theme.colors.text.yellow};
}
`;

export default Wrapper;
140 changes: 140 additions & 0 deletions packages/bruno-app/src/components/FolderSettings/Auth/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ import OAuth2PasswordCredentials from 'components/RequestPane/Auth/OAuth2/Passwo
import OAuth2ClientCredentials from 'components/RequestPane/Auth/OAuth2/ClientCredentials/index';
import GrantTypeSelector from 'components/RequestPane/Auth/OAuth2/GrantTypeSelector/index';
import AuthMode from '../AuthMode';
import BasicAuth from 'components/RequestPane/Auth/BasicAuth';
import BearerAuth from 'components/RequestPane/Auth/BearerAuth';
import DigestAuth from 'components/RequestPane/Auth/DigestAuth';
import NTLMAuth from 'components/RequestPane/Auth/NTLMAuth';
import WsseAuth from 'components/RequestPane/Auth/WsseAuth';
import ApiKeyAuth from 'components/RequestPane/Auth/ApiKeyAuth';
import AwsV4Auth from 'components/RequestPane/Auth/AwsV4Auth';
import { findItemInCollection, findParentItemInCollection, humanizeRequestAuthMode } from 'utils/collections/index';

const GrantTypeComponentMap = ({ collection, folder }) => {
const dispatch = useDispatch();
Expand Down Expand Up @@ -37,12 +45,132 @@ const Auth = ({ collection, folder }) => {
let request = get(folder, 'root.request', {});
const authMode = get(folder, 'root.request.auth.mode');

const getTreePathFromCollectionToFolder = (collection, _folder) => {
let path = [];
let item = findItemInCollection(collection, _folder?.uid);
while (item) {
path.unshift(item);
item = findParentItemInCollection(collection, item?.uid);
}
return path;
};

const getEffectiveAuthSource = () => {
if (authMode !== 'inherit') return null;

const collectionAuth = get(collection, 'root.request.auth');
let effectiveSource = {
type: 'collection',
name: 'Collection',
auth: collectionAuth
};

// Get path from collection to current folder
const folderTreePath = getTreePathFromCollectionToFolder(collection, folder);

// Check parent folders to find closest auth configuration
// Skip the last item which is the current folder
for (let i = 0; i < folderTreePath.length - 1; i++) {
const parentFolder = folderTreePath[i];
if (parentFolder.type === 'folder') {
const folderAuth = get(parentFolder, 'root.request.auth');
if (folderAuth && folderAuth.mode && folderAuth.mode !== 'none' && folderAuth.mode !== 'inherit') {
effectiveSource = {
type: 'folder',
name: parentFolder.name,
auth: folderAuth
};
break;
}
}
}

return effectiveSource;
};

const handleSave = () => {
dispatch(saveFolderRoot(collection.uid, folder.uid));
};

const getAuthView = () => {
switch (authMode) {
case 'basic': {
return (
<BasicAuth
collection={collection}
item={folder}
updateAuth={updateFolderAuth}
request={request}
save={() => handleSave()}
/>
);
}
case 'bearer': {
return (
<BearerAuth
collection={collection}
item={folder}
updateAuth={updateFolderAuth}
request={request}
save={() => handleSave()}
/>
);
}
case 'digest': {
return (
<DigestAuth
collection={collection}
item={folder}
updateAuth={updateFolderAuth}
request={request}
save={() => handleSave()}
/>
);
}
case 'ntlm': {
return (
<NTLMAuth
collection={collection}
item={folder}
updateAuth={updateFolderAuth}
request={request}
save={() => handleSave()}
/>
);
}
case 'wsse': {
return (
<WsseAuth
collection={collection}
item={folder}
updateAuth={updateFolderAuth}
request={request}
save={() => handleSave()}
/>
);
}
case 'apikey': {
return (
<ApiKeyAuth
collection={collection}
item={folder}
updateAuth={updateFolderAuth}
request={request}
save={() => handleSave()}
/>
);
}
case 'awsv4': {
return (
<AwsV4Auth
collection={collection}
item={folder}
updateAuth={updateFolderAuth}
request={request}
save={() => handleSave()}
/>
);
}
case 'oauth2': {
return (
<>
Expand All @@ -56,6 +184,17 @@ const Auth = ({ collection, folder }) => {
</>
);
}
case 'inherit': {
const source = getEffectiveAuthSource();
return (
<>
<div className="flex flex-row w-full mt-2 gap-2">
<div>Auth inherited from {source.name}: </div>
<div className="inherit-mode-text">{humanizeRequestAuthMode(source.auth?.mode)}</div>
</div>
</>
);
}
case 'none': {
return null;
}
Expand All @@ -64,6 +203,7 @@ const Auth = ({ collection, folder }) => {
}
};


return (
<StyledWrapper className="w-full">
<div className="text-xs mb-4 text-muted">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,51 @@ const AuthMode = ({ collection, folder }) => {
<StyledWrapper>
<div className="inline-flex items-center cursor-pointer">
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end">
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onModeChange('awsv4');
}}
>
AWS Sig v4
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onModeChange('basic');
}}
>
Basic Auth
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onModeChange('bearer');
}}
>
Bearer Token
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onModeChange('digest');
}}
>
Digest Auth
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onModeChange('ntlm');
}}
>
NTLM Auth
</div>
<div
className="dropdown-item"
onClick={() => {
Expand All @@ -44,6 +89,33 @@ const AuthMode = ({ collection, folder }) => {
>
OAuth 2.0
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onModeChange('wsse');
}}
>
WSSE Auth
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onModeChange('apikey');
}}
>
API Key
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onModeChange('inherit');
}}
>
Inherit
</div>
<div
className="dropdown-item"
onClick={() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,23 @@ import { IconCaretDown } from '@tabler/icons';
import Dropdown from 'components/Dropdown';
import { useTheme } from 'providers/Theme';
import SingleLineEditor from 'components/SingleLineEditor';
import { updateAuth } from 'providers/ReduxStore/slices/collections';
import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions';
import { sendRequest } from 'providers/ReduxStore/slices/collections/actions';
import StyledWrapper from './StyledWrapper';
import { humanizeRequestAPIKeyPlacement } from 'utils/collections';

const ApiKeyAuth = ({ item, collection }) => {
const ApiKeyAuth = ({ item, collection, updateAuth, request, save }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const dropdownTippyRef = useRef();
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);

const apikeyAuth = item.draft ? get(item, 'draft.request.auth.apikey', {}) : get(item, 'request.auth.apikey', {});
const apikeyAuth = get(request, 'auth.apikey', {});

const handleRun = () => dispatch(sendRequest(item, collection.uid));
const handleSave = () => dispatch(saveRequest(item.uid, collection.uid));

const handleSave = () => {
save();
};

const Icon = forwardRef((props, ref) => {
return (
Expand Down Expand Up @@ -69,6 +71,7 @@ const ApiKeyAuth = ({ item, collection }) => {
onChange={(val) => handleAuthChange('key', val)}
onRun={handleRun}
collection={collection}
item={item}
/>
</div>

Expand All @@ -81,6 +84,8 @@ const ApiKeyAuth = ({ item, collection }) => {
onChange={(val) => handleAuthChange('value', val)}
onRun={handleRun}
collection={collection}
item={item}
isSecret={true}
/>
</div>

Expand All @@ -90,7 +95,7 @@ const ApiKeyAuth = ({ item, collection }) => {
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
dropdownTippyRef?.current?.hide();
handleAuthChange('placement', 'header');
}}
>
Expand All @@ -99,11 +104,11 @@ const ApiKeyAuth = ({ item, collection }) => {
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
dropdownTippyRef?.current?.hide();
handleAuthChange('placement', 'queryparams');
}}
>
Query Params
Query Param
</div>
</Dropdown>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collection
import StyledWrapper from './StyledWrapper';
import { update } from 'lodash';

const AwsV4Auth = ({ onTokenChange, item, collection }) => {
const AwsV4Auth = ({ item, collection, updateAuth, request, save }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();

const awsv4Auth = item.draft ? get(item, 'draft.request.auth.awsv4', {}) : get(item, 'request.auth.awsv4', {});
const awsv4Auth = get(request, 'auth.awsv4', {});

const handleRun = () => dispatch(sendRequest(item, collection.uid));
const handleSave = () => dispatch(saveRequest(item.uid, collection.uid));

const handleSave = () => {
save();
};

const handleAccessKeyIdChange = (accessKeyId) => {
dispatch(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ import { updateAuth } from 'providers/ReduxStore/slices/collections';
import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions';
import StyledWrapper from './StyledWrapper';

const BasicAuth = ({ item, collection }) => {
const BasicAuth = ({ item, collection, updateAuth, request, save }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();

const basicAuth = item.draft ? get(item, 'draft.request.auth.basic', {}) : get(item, 'request.auth.basic', {});
const basicAuth = get(request, 'auth.basic', {});

const handleRun = () => dispatch(sendRequest(item, collection.uid));
const handleSave = () => dispatch(saveRequest(item.uid, collection.uid));

const handleSave = () => {
save();
};

const handleUsernameChange = (username) => {
dispatch(
Expand Down
Loading
Loading