Skip to content

Commit

Permalink
Finish third party integration
Browse files Browse the repository at this point in the history
  • Loading branch information
prateek3255 committed Apr 10, 2024
1 parent 1c78b79 commit e9ba313
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 28 deletions.
13 changes: 11 additions & 2 deletions src/ui/components/deleteCrossButton/DeleteCrossButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,25 @@ import { ReactComponent as CloseIconDefault } from "../../../assets/close-inacti

import "./deleteCrossButton.scss";

export const DeleteCrossButton = ({ onClick, label }: { onClick: () => void; label: string }) => {
export const DeleteCrossButton = ({
onClick,
label,
disabled,
}: {
onClick: () => void;
label: string;
disabled?: boolean;
}) => {
const [isHovered, setIsHovered] = useState(false);
return (
<button
className="delete-cross-button"
onClick={onClick}
disabled={disabled}
aria-label={label}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}>
{isHovered ? <CloseIconActive /> : <CloseIconDefault />}
{isHovered && !disabled ? <CloseIconActive /> : <CloseIconDefault />}
</button>
);
};
5 changes: 5 additions & 0 deletions src/ui/components/deleteCrossButton/deleteCrossButton.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,9 @@
width: 22px;
border: none;
background: transparent;

&:disabled {
cursor: not-allowed;
opacity: 0.5;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ type KeyValueInputProps = {
name: string;
onChange: (value: Array<[string, string | null]>) => void;
fixedFields?: Array<string>;
isOverridden?: boolean;
};

export const KeyValueInput = (props: KeyValueInputProps) => {
const { label, value, tooltip, isRequired, name, fixedFields } = props;
const { label, value, tooltip, isRequired, name, fixedFields, isOverridden } = props;
return (
<div className="key-value-input-container">
<ThirdPartyProviderInputLabel
Expand All @@ -40,14 +41,14 @@ export const KeyValueInput = (props: KeyValueInputProps) => {
/>
<div className="key-value-input-container__fields-container">
<div className="key-value-input-container__fields-list">
{value.map((pair, index) => {
{value.slice(0, isOverridden ? 1 : value.length).map((pair, index) => {
return (
<div
className="key-value-input-container__field"
key={index}>
<ThirdPartyProviderInput
value={pair[0]}
disabled={fixedFields?.includes(pair[0])}
value={isOverridden ? "Custom Override" : pair[0]}
disabled={fixedFields?.includes(pair[0]) || isOverridden}
handleChange={(e) => {
const newValue: Array<[string, string | null]> = [
...props.value.slice(0, index),
Expand All @@ -61,8 +62,8 @@ export const KeyValueInput = (props: KeyValueInputProps) => {
type="text"
/>
<ThirdPartyProviderInput
value={pair[1] ?? ""}
disabled={fixedFields?.includes(pair[0])}
value={isOverridden ? "Custom Override" : pair[1] ?? ""}
disabled={fixedFields?.includes(pair[0]) || isOverridden}
handleChange={(e) => {
const newValue: Array<[string, string | null]> = [
...props.value.slice(0, index),
Expand All @@ -75,10 +76,11 @@ export const KeyValueInput = (props: KeyValueInputProps) => {
name={`value-${name}-${index}`}
type="text"
/>
{value.length > 1 && fixedFields?.includes(pair[0]) === false && (
{value.length > 1 && (
<DeleteCrossButton
onClick={() => props.onChange(props.value.filter((_, i) => i !== index))}
label="Delete"
disabled={fixedFields?.includes(pair[0])}
/>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -480,51 +480,84 @@ export const ProviderInfoForm = ({
label="Authorization Endpoint"
tooltip="The authorization endpoint of the provider."
type="text"
disabled={providerConfig?.isGetAuthorisationRedirectUrlOverridden}
error={errorState.authorizationEndpoint}
forceShowError
name="authorizationEndpoint"
value={providerConfigState.authorizationEndpoint}
value={
providerConfig?.isGetAuthorisationRedirectUrlOverridden
? "Custom Override"
: providerConfigState.authorizationEndpoint
}
handleChange={handleFieldChange}
/>
<KeyValueInput
label="Authorization Endpoint Query Params"
name="authorizationEndpointQueryParams"
tooltip="The query params to be sent to the authorization endpoint."
value={providerConfigState.authorizationEndpointQueryParams}
isOverridden={providerConfig?.isGetAuthorisationRedirectUrlOverridden}
onChange={(value) => {
setProviderConfigState((prev) => ({ ...prev, authorizationEndpointQueryParams: value }));
}}
/>

{providerConfig?.isGetAuthorisationRedirectUrlOverridden && (
<div className="overridden-info">
<b>Note:</b> You cannot edit the above fields because this provider is using a custom override
for <code>getAuthorisationRedirectUrl</code>
</div>
)}

<div className="custom-provider-divider" />
<ThirdPartyProviderInput
label="Token Endpoint"
tooltip="The token endpoint of the provider."
type="text"
disabled={providerConfig?.isExchangeAuthCodeForOAuthTokensOverridden}
name="tokenEndpoint"
error={errorState.tokenEndpoint}
forceShowError
value={providerConfigState.tokenEndpoint}
value={
providerConfig?.isExchangeAuthCodeForOAuthTokensOverridden
? "Custom Override"
: providerConfigState.tokenEndpoint
}
handleChange={handleFieldChange}
/>
<KeyValueInput
label="Token Endpoint Body Params"
name="tokenEndpointBodyParams"
tooltip="The body params to be sent to the token endpoint."
isOverridden={providerConfig?.isExchangeAuthCodeForOAuthTokensOverridden}
value={providerConfigState.tokenEndpointBodyParams}
onChange={(value) => {
setProviderConfigState((prev) => ({ ...prev, tokenEndpointBodyParams: value }));
}}
/>

{providerConfig?.isExchangeAuthCodeForOAuthTokensOverridden && (
<div className="overridden-info">
<b>Note:</b> You cannot edit the above fields because this provider is using a custom override
for <code>exchangeAuthCodeForOAuthTokens</code>
</div>
)}

<div className="custom-provider-divider" />

<ThirdPartyProviderInput
label="User Info Endpoint"
tooltip="The user info endpoint of the provider."
type="text"
name="userInfoEndpoint"
disabled={providerConfig?.isGetUserInfoOverridden}
error={errorState.userInfoEndpoint}
forceShowError
value={providerConfigState.userInfoEndpoint}
value={
providerConfig?.isGetUserInfoOverridden
? "Custom Override"
: providerConfigState.userInfoEndpoint
}
handleChange={handleFieldChange}
/>

Expand All @@ -533,6 +566,7 @@ export const ProviderInfoForm = ({
name="userInfoEndpointQueryParams"
tooltip="The query params to be sent to the user info endpoint."
value={providerConfigState.userInfoEndpointQueryParams}
isOverridden={providerConfig?.isGetUserInfoOverridden}
onChange={(value) => {
setProviderConfigState((prev) => ({ ...prev, userInfoEndpointQueryParams: value }));
}}
Expand All @@ -543,6 +577,7 @@ export const ProviderInfoForm = ({
name="userInfoEndpointHeaders"
tooltip="The headers to be sent to the user info endpoint."
value={providerConfigState.userInfoEndpointHeaders}
isOverridden={providerConfig?.isGetUserInfoOverridden}
onChange={(value) => {
setProviderConfigState((prev) => ({ ...prev, userInfoEndpointHeaders: value }));
}}
Expand All @@ -552,16 +587,23 @@ export const ProviderInfoForm = ({
label="User Info Map from UserInfo API"
tooltip="The mapping of the user info fields to the user info API."
name="fromUserInfoAPI"
isOverridden={providerConfig?.isGetUserInfoOverridden}
hasEmailOverrides
value={
providerConfigState.userInfoMap.fromUserInfoAPI ?? { userId: "", email: "", emailVerified: "" }
}
handleChange={handleUserInfoFieldChange}
requireEmail={providerConfigState.requireEmail}
handleRequireEmailChange={(value) => {
setProviderConfigState((prev) => ({ ...prev, requireEmail: value }));
}}
/>

<UserInfoMap
label="User Info Map from Id Token Payload"
tooltip="The mapping of the user info fields to the id token payload."
name="fromIdTokenPayload"
isOverridden={providerConfig?.isGetUserInfoOverridden}
value={
providerConfigState.userInfoMap.fromIdTokenPayload ?? {
userId: "",
Expand All @@ -572,6 +614,13 @@ export const ProviderInfoForm = ({
handleChange={handleUserInfoFieldChange}
/>

{providerConfig?.isGetUserInfoOverridden && (
<div className="overridden-info">
<b>Note:</b> You cannot edit the above fields because this provider is using a custom override
for <code>getUserInfo</code>
</div>
)}

<div className="custom-provider-divider" />

<ThirdPartyProviderInput
Expand Down Expand Up @@ -632,6 +681,10 @@ const UserInfoMap = ({
name,
value,
handleChange,
isOverridden,
hasEmailOverrides,
requireEmail,
handleRequireEmailChange,
}: {
label: string;
tooltip: string;
Expand All @@ -650,7 +703,29 @@ const UserInfoMap = ({
key: string;
value: string;
}) => void;
isOverridden?: boolean;
hasEmailOverrides?: boolean;
requireEmail?: boolean;
handleRequireEmailChange?: (value: boolean) => void;
}) => {
const [emailSelectValue, setEmailSelectValue] = useState<EmailSelectState>(() => {
if (requireEmail === false) {
return "never";
}
return "always";
});

const handleEmailSelectChange = (value: EmailSelectState) => {
setEmailSelectValue(value);
if (value === "never" && handleRequireEmailChange) {
handleRequireEmailChange(false);
} else if (value === "always" && handleRequireEmailChange) {
handleRequireEmailChange(true);
}
};

const isEmailFieldVisible = isOverridden || !hasEmailOverrides || emailSelectValue === "always";

return (
<div className="user-info-map">
<ThirdPartyProviderInputLabel
Expand All @@ -663,7 +738,8 @@ const UserInfoMap = ({
type="text"
name={`userId-${name}`}
minLabelWidth={130}
value={value.userId}
disabled={isOverridden}
value={isOverridden ? "Custom Override" : value.userId}
handleChange={(e) =>
handleChange({
name,
Expand All @@ -672,26 +748,47 @@ const UserInfoMap = ({
})
}
/>
<ThirdPartyProviderInput
label="email"
type="text"
name={`email-${name}`}
minLabelWidth={130}
value={value.email}
handleChange={(e) =>
handleChange({
name,
key: "email",
value: e.target.value,
})
}
/>
{!isOverridden && hasEmailOverrides && (
<div className="provider-email-select">
<ThirdPartyProviderInputLabel label="How often does the provider return email?" />
<EmailSelect
value={emailSelectValue}
setValue={handleEmailSelectChange}
/>
</div>
)}
{(emailSelectValue === "sometimes" || emailSelectValue === "never") && (
<div className="overridden-info">
<b>Note:</b>{" "}
{emailSelectValue === "never"
? "We will generate a fake email for the end users automatically using their user id. If you want override how the fake email is generated by the SDK you can do so by overriding the generateFakeEmail method in the provider config"
: "Add a custom override for the getUserInfo method for this provider to handle the case when provider doesn't return email."}
</div>
)}
{isEmailFieldVisible && (
<ThirdPartyProviderInput
label="email"
type="text"
name={`email-${name}`}
disabled={isOverridden}
minLabelWidth={130}
value={isOverridden ? "Custom Override" : value.email}
handleChange={(e) =>
handleChange({
name,
key: "email",
value: e.target.value,
})
}
/>
)}
<ThirdPartyProviderInput
label="emailVerified"
type="text"
name="emailVerified"
disabled={isOverridden}
minLabelWidth={130}
value={value.emailVerified}
value={isOverridden ? "Custom Override" : value.emailVerified}
handleChange={(e) =>
handleChange({
name,
Expand All @@ -705,6 +802,38 @@ const UserInfoMap = ({
);
};

type EmailSelectState = "always" | "sometimes" | "never";

const EmailSelectValues: Array<{ label: string; value: EmailSelectState }> = [
{
label: "All the time",
value: "always",
},
{
label: "Sometimes",
value: "sometimes",
},
{
label: "Never",
value: "never",
},
];

const EmailSelect = ({ value, setValue }: { value: EmailSelectState; setValue: (value: EmailSelectState) => void }) => {
return (
<div className="email-select-container">
{EmailSelectValues.map((option) => (
<button
key={option.value}
className={`email-select-option ${value === option.value ? "email-select-option--selected" : ""}`}
onClick={() => setValue(option.value)}>
{option.label}
</button>
))}
</div>
);
};

type ProviderConfigState = Omit<
Required<ProviderConfig>,
| "tokenEndpointBodyParams"
Expand Down
Loading

0 comments on commit e9ba313

Please sign in to comment.