mirror of
https://github.com/usebruno/bruno.git
synced 2024-11-25 01:14:23 +01:00
feat(#119): ui placeholders for basic and bearer auths
This commit is contained in:
parent
51ee37cf96
commit
0f1e330dc5
@ -0,0 +1,25 @@
|
|||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
|
||||||
|
.auth-mode-selector {
|
||||||
|
background: ${(props) => props.theme.requestTabPanel.bodyModeSelect.color};
|
||||||
|
border-radius: 3px;
|
||||||
|
|
||||||
|
.dropdown-item {
|
||||||
|
padding: 0.2rem 0.6rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-item {
|
||||||
|
padding: 0.2rem 0.6rem !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.caret {
|
||||||
|
color: rgb(140, 140, 140);
|
||||||
|
fill: rgb(140 140 140);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default Wrapper;
|
@ -0,0 +1,70 @@
|
|||||||
|
import React, { useRef, forwardRef } from 'react';
|
||||||
|
import get from 'lodash/get';
|
||||||
|
import { IconCaretDown } from '@tabler/icons';
|
||||||
|
import Dropdown from 'components/Dropdown';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { updateRequestAuthMode } from 'providers/ReduxStore/slices/collections';
|
||||||
|
import { humanizeRequestAuthMode } from 'utils/collections';
|
||||||
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
|
const AuthMode = ({ item, collection }) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const dropdownTippyRef = useRef();
|
||||||
|
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
|
||||||
|
const authMode = item.draft ? get(item, 'draft.request.auth.mode') : get(item, 'request.auth.mode');
|
||||||
|
|
||||||
|
const Icon = forwardRef((props, ref) => {
|
||||||
|
return (
|
||||||
|
<div ref={ref} className="flex items-center justify-center pl-3 py-1 select-none">
|
||||||
|
{humanizeRequestAuthMode(authMode)} <IconCaretDown className="caret ml-2 mr-2" size={14} strokeWidth={2} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const onModeChange = (value) => {
|
||||||
|
dispatch(
|
||||||
|
updateRequestAuthMode({
|
||||||
|
itemUid: item.uid,
|
||||||
|
collectionUid: collection.uid,
|
||||||
|
mode: value
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledWrapper>
|
||||||
|
<div className="inline-flex items-center cursor-pointer auth-mode-selector">
|
||||||
|
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end">
|
||||||
|
<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('none');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
No Auth
|
||||||
|
</div>
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
</StyledWrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default AuthMode;
|
@ -0,0 +1,5 @@
|
|||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const Wrapper = styled.div``;
|
||||||
|
|
||||||
|
export default Wrapper;
|
32
packages/bruno-app/src/components/RequestPane/Auth/index.js
Normal file
32
packages/bruno-app/src/components/RequestPane/Auth/index.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import get from 'lodash/get';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { updateRequestBody } from 'providers/ReduxStore/slices/collections';
|
||||||
|
import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
|
const RequestBody = ({ item, collection }) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const authMode = item.draft ? get(item, 'draft.request.auth.mode') : get(item, 'request.auth.mode');
|
||||||
|
|
||||||
|
const onEdit = (value) => {
|
||||||
|
// dispatch(
|
||||||
|
// updateRequestBody({
|
||||||
|
// content: value,
|
||||||
|
// itemUid: item.uid,
|
||||||
|
// collectionUid: collection.uid
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
};
|
||||||
|
|
||||||
|
if (authMode === 'basic') {
|
||||||
|
return <div>Basic Auth</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authMode === 'bearer') {
|
||||||
|
return <div>Bearer Token</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <StyledWrapper className="w-full">No Auth</StyledWrapper>;
|
||||||
|
};
|
||||||
|
export default RequestBody;
|
@ -7,6 +7,8 @@ import QueryParams from 'components/RequestPane/QueryParams';
|
|||||||
import RequestHeaders from 'components/RequestPane/RequestHeaders';
|
import RequestHeaders from 'components/RequestPane/RequestHeaders';
|
||||||
import RequestBody from 'components/RequestPane/RequestBody';
|
import RequestBody from 'components/RequestPane/RequestBody';
|
||||||
import RequestBodyMode from 'components/RequestPane/RequestBody/RequestBodyMode';
|
import RequestBodyMode from 'components/RequestPane/RequestBody/RequestBodyMode';
|
||||||
|
import Auth from 'components/RequestPane/Auth';
|
||||||
|
import AuthMode from 'components/RequestPane/Auth/AuthMode';
|
||||||
import Vars from 'components/RequestPane/Vars';
|
import Vars from 'components/RequestPane/Vars';
|
||||||
import Assertions from 'components/RequestPane/Assertions';
|
import Assertions from 'components/RequestPane/Assertions';
|
||||||
import Script from 'components/RequestPane/Script';
|
import Script from 'components/RequestPane/Script';
|
||||||
@ -38,6 +40,9 @@ const HttpRequestPane = ({ item, collection, leftPaneWidth }) => {
|
|||||||
case 'headers': {
|
case 'headers': {
|
||||||
return <RequestHeaders item={item} collection={collection} />;
|
return <RequestHeaders item={item} collection={collection} />;
|
||||||
}
|
}
|
||||||
|
case 'auth': {
|
||||||
|
return <Auth item={item} collection={collection} />;
|
||||||
|
}
|
||||||
case 'vars': {
|
case 'vars': {
|
||||||
return <Vars item={item} collection={collection} />;
|
return <Vars item={item} collection={collection} />;
|
||||||
}
|
}
|
||||||
@ -83,6 +88,9 @@ const HttpRequestPane = ({ item, collection, leftPaneWidth }) => {
|
|||||||
<div className={getTabClassname('headers')} role="tab" onClick={() => selectTab('headers')}>
|
<div className={getTabClassname('headers')} role="tab" onClick={() => selectTab('headers')}>
|
||||||
Headers
|
Headers
|
||||||
</div>
|
</div>
|
||||||
|
<div className={getTabClassname('auth')} role="tab" onClick={() => selectTab('auth')}>
|
||||||
|
Auth
|
||||||
|
</div>
|
||||||
<div className={getTabClassname('vars')} role="tab" onClick={() => selectTab('vars')}>
|
<div className={getTabClassname('vars')} role="tab" onClick={() => selectTab('vars')}>
|
||||||
Vars
|
Vars
|
||||||
</div>
|
</div>
|
||||||
@ -95,13 +103,16 @@ const HttpRequestPane = ({ item, collection, leftPaneWidth }) => {
|
|||||||
<div className={getTabClassname('tests')} role="tab" onClick={() => selectTab('tests')}>
|
<div className={getTabClassname('tests')} role="tab" onClick={() => selectTab('tests')}>
|
||||||
Tests
|
Tests
|
||||||
</div>
|
</div>
|
||||||
{/* Moved to post mvp */}
|
|
||||||
{/* <div className={getTabClassname('auth')} role="tab" onClick={() => selectTab('auth')}>Auth</div> */}
|
|
||||||
{focusedTab.requestPaneTab === 'body' ? (
|
{focusedTab.requestPaneTab === 'body' ? (
|
||||||
<div className="flex flex-grow justify-end items-center">
|
<div className="flex flex-grow justify-end items-center">
|
||||||
<RequestBodyMode item={item} collection={collection} />
|
<RequestBodyMode item={item} collection={collection} />
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
{focusedTab.requestPaneTab === 'auth' ? (
|
||||||
|
<div className="flex flex-grow justify-end items-center">
|
||||||
|
<AuthMode item={item} collection={collection} />
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<section className={`flex w-full ${['script', 'vars'].includes(focusedTab.requestPaneTab) ? '' : 'mt-5'}`}>
|
<section className={`flex w-full ${['script', 'vars'].includes(focusedTab.requestPaneTab) ? '' : 'mt-5'}`}>
|
||||||
{getTabPanel(focusedTab.requestPaneTab)}
|
{getTabPanel(focusedTab.requestPaneTab)}
|
||||||
|
@ -563,6 +563,20 @@ export const collectionsSlice = createSlice({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
updateRequestAuthMode: (state, action) => {
|
||||||
|
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
||||||
|
|
||||||
|
if (collection && collection.items && collection.items.length) {
|
||||||
|
const item = findItemInCollection(collection, action.payload.itemUid);
|
||||||
|
|
||||||
|
if (item && isItemARequest(item)) {
|
||||||
|
if (!item.draft) {
|
||||||
|
item.draft = cloneDeep(item);
|
||||||
|
}
|
||||||
|
item.draft.request.auth.mode = action.payload.mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
updateRequestBodyMode: (state, action) => {
|
updateRequestBodyMode: (state, action) => {
|
||||||
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
||||||
|
|
||||||
@ -1170,6 +1184,7 @@ export const {
|
|||||||
addMultipartFormParam,
|
addMultipartFormParam,
|
||||||
updateMultipartFormParam,
|
updateMultipartFormParam,
|
||||||
deleteMultipartFormParam,
|
deleteMultipartFormParam,
|
||||||
|
updateRequestAuthMode,
|
||||||
updateRequestBodyMode,
|
updateRequestBodyMode,
|
||||||
updateRequestBody,
|
updateRequestBody,
|
||||||
updateRequestGraphqlQuery,
|
updateRequestGraphqlQuery,
|
||||||
|
@ -445,6 +445,22 @@ export const humanizeRequestBodyMode = (mode) => {
|
|||||||
return label;
|
return label;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const humanizeRequestAuthMode = (mode) => {
|
||||||
|
let label = 'No Auth';
|
||||||
|
switch (mode) {
|
||||||
|
case 'basic': {
|
||||||
|
label = 'Basic Auth';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'bearer': {
|
||||||
|
label = 'Bearer Token';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return label;
|
||||||
|
};
|
||||||
|
|
||||||
export const refreshUidsInItem = (item) => {
|
export const refreshUidsInItem = (item) => {
|
||||||
item.uid = uuid();
|
item.uid = uuid();
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ const bruToJson = (bru) => {
|
|||||||
url: _.get(json, 'http.url'),
|
url: _.get(json, 'http.url'),
|
||||||
params: _.get(json, 'query', []),
|
params: _.get(json, 'query', []),
|
||||||
headers: _.get(json, 'headers', []),
|
headers: _.get(json, 'headers', []),
|
||||||
|
auth: _.get(json, 'auth', {}),
|
||||||
body: _.get(json, 'body', {}),
|
body: _.get(json, 'body', {}),
|
||||||
script: _.get(json, 'script', {}),
|
script: _.get(json, 'script', {}),
|
||||||
vars: _.get(json, 'vars', {}),
|
vars: _.get(json, 'vars', {}),
|
||||||
@ -69,6 +70,7 @@ const bruToJson = (bru) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
transformedJson.request.auth.mode = _.get(json, 'http.auth', 'none');
|
||||||
transformedJson.request.body.mode = _.get(json, 'http.body', 'none');
|
transformedJson.request.body.mode = _.get(json, 'http.body', 'none');
|
||||||
|
|
||||||
return transformedJson;
|
return transformedJson;
|
||||||
@ -104,10 +106,12 @@ const jsonToBru = (json) => {
|
|||||||
http: {
|
http: {
|
||||||
method: _.lowerCase(_.get(json, 'request.method')),
|
method: _.lowerCase(_.get(json, 'request.method')),
|
||||||
url: _.get(json, 'request.url'),
|
url: _.get(json, 'request.url'),
|
||||||
|
auth: _.get(json, 'request.auth.mode', 'none'),
|
||||||
body: _.get(json, 'request.body.mode', 'none')
|
body: _.get(json, 'request.body.mode', 'none')
|
||||||
},
|
},
|
||||||
query: _.get(json, 'request.params', []),
|
query: _.get(json, 'request.params', []),
|
||||||
headers: _.get(json, 'request.headers', []),
|
headers: _.get(json, 'request.headers', []),
|
||||||
|
auth: _.get(json, 'request.auth', {}),
|
||||||
body: _.get(json, 'request.body', {}),
|
body: _.get(json, 'request.body', {}),
|
||||||
script: _.get(json, 'request.script', {}),
|
script: _.get(json, 'request.script', {}),
|
||||||
vars: {
|
vars: {
|
||||||
|
@ -69,6 +69,27 @@ const requestBodySchema = Yup.object({
|
|||||||
.noUnknown(true)
|
.noUnknown(true)
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
|
const authBasicSchema = Yup.object({
|
||||||
|
username: Yup.string().nullable(),
|
||||||
|
password: Yup.string().nullable()
|
||||||
|
})
|
||||||
|
.noUnknown(true)
|
||||||
|
.strict();
|
||||||
|
|
||||||
|
const authBearerSchema = Yup.object({
|
||||||
|
token: Yup.string().nullable()
|
||||||
|
})
|
||||||
|
.noUnknown(true)
|
||||||
|
.strict();
|
||||||
|
|
||||||
|
const authSchema = Yup.object({
|
||||||
|
mode: Yup.string().oneOf(['none', 'basic', 'bearer']).required('mode is required'),
|
||||||
|
basic: authBasicSchema.nullable(),
|
||||||
|
bearer: authBearerSchema.nullable()
|
||||||
|
})
|
||||||
|
.noUnknown(true)
|
||||||
|
.strict();
|
||||||
|
|
||||||
// Right now, the request schema is very tightly coupled with http request
|
// Right now, the request schema is very tightly coupled with http request
|
||||||
// As we introduce more request types in the future, we will improve the definition to support
|
// As we introduce more request types in the future, we will improve the definition to support
|
||||||
// schema structure based on other request type
|
// schema structure based on other request type
|
||||||
@ -77,6 +98,7 @@ const requestSchema = Yup.object({
|
|||||||
method: requestMethodSchema,
|
method: requestMethodSchema,
|
||||||
headers: Yup.array().of(keyValueSchema).required('headers are required'),
|
headers: Yup.array().of(keyValueSchema).required('headers are required'),
|
||||||
params: Yup.array().of(keyValueSchema).required('params are required'),
|
params: Yup.array().of(keyValueSchema).required('params are required'),
|
||||||
|
auth: authSchema,
|
||||||
body: requestBodySchema,
|
body: requestBodySchema,
|
||||||
script: Yup.object({
|
script: Yup.object({
|
||||||
req: Yup.string().nullable(),
|
req: Yup.string().nullable(),
|
||||||
|
Loading…
Reference in New Issue
Block a user