Merge remote-tracking branch 'pietrygamat/feature/inherit-oauth' into pietrygamat/inherit-oauth

This commit is contained in:
lohxt1
2025-01-11 12:21:45 +05:30
20 changed files with 265 additions and 176 deletions

View File

@@ -86,7 +86,7 @@ const AuthMode = ({ collection }) => {
onModeChange('oauth2');
}}
>
Oauth2
OAuth 2.0
</div>
<div
className="dropdown-item"

View File

@@ -7,8 +7,6 @@ import { saveCollectionRoot, sendCollectionOauth2Request } from 'providers/Redux
import StyledWrapper from './StyledWrapper';
import { inputsConfig } from './inputsConfig';
import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections/index';
import { clearOauth2Cache } from 'utils/network/index';
import toast from 'react-hot-toast';
const OAuth2AuthorizationCode = ({ collection }) => {
const dispatch = useDispatch();
@@ -64,17 +62,6 @@ const OAuth2AuthorizationCode = ({ collection }) => {
})
);
};
const handleClearCache = (e) => {
clearOauth2Cache(collection?.uid)
.then(() => {
toast.success('cleared cache successfully');
})
.catch((err) => {
toast.error(err.message);
});
};
return (
<StyledWrapper className="mt-2 flex w-full gap-4 flex-col">
{inputsConfig.map((input) => {
@@ -105,14 +92,6 @@ const OAuth2AuthorizationCode = ({ collection }) => {
onChange={handlePKCEToggle}
/>
</div>
<div className="flex flex-row gap-4">
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
</button>
<button onClick={handleClearCache} className="submit btn btn-sm btn-secondary w-fit">
Clear Cache
</button>
</div>
</StyledWrapper>
);
};

View File

@@ -60,9 +60,6 @@ const OAuth2ClientCredentials = ({ collection }) => {
</div>
);
})}
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
</button>
</StyledWrapper>
);
};

View File

@@ -6,9 +6,9 @@ import SingleLineEditor from 'components/SingleLineEditor';
import { saveCollectionRoot, sendCollectionOauth2Request } from 'providers/ReduxStore/slices/collections/actions';
import StyledWrapper from './StyledWrapper';
import { inputsConfig } from './inputsConfig';
import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections/index';
import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections';
const OAuth2AuthorizationCode = ({ item, collection }) => {
const OAuth2PasswordCredentials = ({ collection }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
@@ -62,11 +62,8 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
</div>
);
})}
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
</button>
</StyledWrapper>
);
};
export default OAuth2AuthorizationCode;
export default OAuth2PasswordCredentials;

View File

@@ -5,6 +5,7 @@ import GrantTypeSelector from './GrantTypeSelector/index';
import OAuth2PasswordCredentials from './PasswordCredentials/index';
import OAuth2AuthorizationCode from './AuthorizationCode/index';
import OAuth2ClientCredentials from './ClientCredentials/index';
import CredentialsPreview from 'components/RequestPane/Auth/OAuth2/CredentialsPreview';
const grantTypeComponentMap = (grantType, collection) => {
switch (grantType) {
@@ -30,6 +31,7 @@ const OAuth2 = ({ collection }) => {
<StyledWrapper className="mt-2 w-full">
<GrantTypeSelector collection={collection} />
{grantTypeComponentMap(oAuth?.grantType, collection)}
<CredentialsPreview collection={collection} />
</StyledWrapper>
);
};

View File

@@ -7,8 +7,6 @@ import { updateAuth } from 'providers/ReduxStore/slices/collections';
import { saveRequest, sendRequest } from 'providers/ReduxStore/slices/collections/actions';
import StyledWrapper from './StyledWrapper';
import { inputsConfig } from './inputsConfig';
import { clearOauth2Cache } from 'utils/network/index';
import toast from 'react-hot-toast';
const OAuth2AuthorizationCode = ({ item, collection }) => {
const dispatch = useDispatch();
@@ -67,16 +65,6 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
);
};
const handleClearCache = (e) => {
clearOauth2Cache(collection?.uid)
.then(() => {
toast.success('cleared cache successfully');
})
.catch((err) => {
toast.error(err.message);
});
};
return (
<StyledWrapper className="mt-2 flex w-full gap-4 flex-col">
{inputsConfig.map((input) => {
@@ -108,14 +96,6 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
onChange={handlePKCEToggle}
/>
</div>
<div className="flex flex-row gap-4">
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
</button>
<button onClick={handleClearCache} className="submit btn btn-sm btn-secondary w-fit">
Clear Cache
</button>
</div>
</StyledWrapper>
);
};

View File

@@ -62,9 +62,6 @@ const OAuth2ClientCredentials = ({ item, collection }) => {
</div>
);
})}
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
</button>
</StyledWrapper>
);
};

View File

@@ -0,0 +1,17 @@
import styled from 'styled-components';
const Wrapper = styled.div`
label {
display: block;
font-size: 0.8125rem;
}
textarea {
height: fit-content;
max-width: 400px;
border: solid 1px ${(props) => props.theme.input.border};
background-color: ${(props) => props.theme.input.bg};
}
`;
export default Wrapper;

View File

@@ -0,0 +1,80 @@
import React, { useEffect, useState } from 'react';
import { clearOauth2Cache, readOauth2CachedCredentials } from 'utils/network';
import { sendCollectionOauth2Request, sendRequest } from 'providers/ReduxStore/slices/collections/actions';
import toast from 'react-hot-toast';
import { useDispatch } from 'react-redux';
import StyledWrapper from './StyledWrapper';
const CredentialsPreview = ({ item, collection }) => {
const oauth2CredentialsAreaRef = React.createRef();
const [oauth2Credentials, setOauth2Credentials] = useState({});
const dispatch = useDispatch();
useEffect(() => {
oauth2CredentialsAreaRef.current.value = oauth2Credentials;
readOauth2CachedCredentials(collection.uid).then((credentials) => setOauth2Credentials(credentials));
}, [oauth2CredentialsAreaRef]);
const handleRun = async () => {
if (item) {
dispatch(sendRequest(item, collection.uid));
} else {
dispatch(sendCollectionOauth2Request(collection.uid));
}
};
const handleClearCache = (e) => {
clearOauth2Cache(collection?.uid)
.then(() => {
readOauth2CachedCredentials(collection.uid).then((credentials) => {
setOauth2Credentials(credentials);
toast.success('Cleared cache successfully');
});
})
.catch((err) => {
toast.error(err.message);
});
};
const sortedFields = () => {
const tokens = {};
const extras = {};
Object.entries(oauth2Credentials).forEach(([key, value]) => {
if (key.endsWith('_token')) {
tokens[key] = value;
} else {
extras[key] = value;
}
});
return { ...tokens, ...extras };
};
return (
<StyledWrapper className="flex flex-col w-full gap-1 mt-4">
<div className="credential-item-wrapper" ref={oauth2CredentialsAreaRef}>
{Object.entries(oauth2Credentials).length > 0 ? (
<>
<button onClick={handleClearCache} className="submit btn btn-sm btn-secondary w-fit">
Clear Access Token Cache
</button>
<details className="cursor-pointer flex flex-row w-full mt-2 gap-2">
<summary>Cached OAuth2 Credentials</summary>
{Object.entries(sortedFields()).map(([field, value]) => (
<div key={field}>
<label className="text-xs">{field}</label>
<textarea className="w-full h-24 p-2 text-xs border rounded" value={value} readOnly />
</div>
))}
</details>
</>
) : (
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
</button>
)}
</div>
</StyledWrapper>
);
};
export default CredentialsPreview;

View File

@@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import get from 'lodash/get';
import { useTheme } from 'providers/Theme';
import { useDispatch } from 'react-redux';
@@ -8,7 +8,7 @@ import { saveRequest, sendRequest } from 'providers/ReduxStore/slices/collection
import StyledWrapper from './StyledWrapper';
import { inputsConfig } from './inputsConfig';
const OAuth2AuthorizationCode = ({ item, collection }) => {
const OAuth2PasswordCredentials = ({ item, collection }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
@@ -64,11 +64,8 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
</div>
);
})}
<button onClick={handleRun} className="submit btn btn-sm btn-secondary w-fit">
Get Access Token
</button>
</StyledWrapper>
);
};
export default OAuth2AuthorizationCode;
export default OAuth2PasswordCredentials;

View File

@@ -5,6 +5,7 @@ import GrantTypeSelector from './GrantTypeSelector/index';
import OAuth2PasswordCredentials from './PasswordCredentials/index';
import OAuth2AuthorizationCode from './AuthorizationCode/index';
import OAuth2ClientCredentials from './ClientCredentials/index';
import CredentialsPreview from './CredentialsPreview';
const grantTypeComponentMap = (grantType, item, collection) => {
switch (grantType) {
@@ -30,6 +31,7 @@ const OAuth2 = ({ item, collection }) => {
<StyledWrapper className="mt-2 w-full">
<GrantTypeSelector item={item} collection={collection} />
{grantTypeComponentMap(oAuth?.grantType, item, collection)}
<CredentialsPreview item={item} collection={collection} />
</StyledWrapper>
);
};

View File

@@ -8,8 +8,9 @@ import DigestAuth from './DigestAuth';
import WsseAuth from './WsseAuth';
import ApiKeyAuth from './ApiKeyAuth';
import StyledWrapper from './StyledWrapper';
import { humanizeRequestAuthMode } from 'utils/collections/index';
import { humanizeRequestAuthMode } from 'utils/collections';
import OAuth2 from './OAuth2/index';
import CredentialsPreview from './OAuth2/CredentialsPreview';
const Auth = ({ item, collection }) => {
const authMode = item.draft ? get(item, 'draft.request.auth.mode') : get(item, 'request.auth.mode');
@@ -42,24 +43,13 @@ const Auth = ({ item, collection }) => {
}
case 'inherit': {
return (
<div className="flex flex-row w-full mt-2 gap-2">
{collectionAuth?.mode === 'oauth2' ? (
<div className="flex flex-col gap-2">
<div className="flex flex-row gap-1">
<div>Collection level auth is: </div>
<div className="inherit-mode-text">{humanizeRequestAuthMode(collectionAuth?.mode)}</div>
</div>
<div className="text-sm opacity-50">
Note: You need to use scripting to set the access token in the request headers.
</div>
</div>
) : (
<>
<div>Auth inherited from the Collection: </div>
<div className="inherit-mode-text">{humanizeRequestAuthMode(collectionAuth?.mode)}</div>
</>
)}
</div>
<>
<div className="flex flex-row w-full mt-2 gap-2">
<div>Auth inherited from the Collection: </div>
<div className="inherit-mode-text">{humanizeRequestAuthMode(collectionAuth?.mode)}</div>
</div>
{collectionAuth?.mode === 'oauth2' && <CredentialsPreview item={item} collection={collection} />}
</>
);
}
}

View File

@@ -50,6 +50,13 @@ export const clearOauth2Cache = async (uid) => {
});
};
export const readOauth2CachedCredentials = async (uid) => {
return new Promise((resolve, reject) => {
const { ipcRenderer } = window;
ipcRenderer.invoke('read-oauth2-cached-credentials', uid).then(resolve).catch(reject);
});
};
export const fetchGqlSchema = async (endpoint, environment, request, collection) => {
return new Promise((resolve, reject) => {
const { ipcRenderer } = window;