Skip to content

Commit

Permalink
Merge branch 'feat/mfa/base' into feat/mfa/recipe-setup
Browse files Browse the repository at this point in the history
  • Loading branch information
porcellus committed Dec 9, 2023
2 parents 9d8fae1 + 9a7c5d0 commit 2a6ab14
Show file tree
Hide file tree
Showing 67 changed files with 1,994 additions and 753 deletions.
90 changes: 90 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,96 @@ To use this you'll need compatible versions:
- Added a `useShadowDom` prop to the `AccessDeniedScreen`
- Added an `error` prop to the `AccessDeniedScreen` that can be used to describe the reason access is denied.

## [0.35.9] - 2023-12-06

- Fixes ThirdPartyEmailPassword rendering sign in/up switcher even with disabled email password. Instead it'll now render `SignInAndUpHeader_Override` in this case (overrideable as `ThirdPartySignInAndUpHeader`). Overriding `ThirdPartyEmailPasswordHeader_Override` should still cover all cases.
- Added a new prop to `ThirdPartyEmailPasswordHeader_Override` you can use to check if email password is enabled.

## [0.35.8] - 2023-11-26

- Fixes `inputComponent` props to make them non optional. This is in the context of customizing the sign up form to add custom react components.

## [0.35.7] - 2023-11-24

### Added

- EmailPassword and ThirdPartyEmailPassword recipe enhancements:
- Introduced the capability to utilize custom components by exposing `inputComponent` types.
- Allow setting default values in signup/signin form fields.
- Made the `onChange` prop in `inputComponent` simpler by removing the need for an `id` attribute.
- Added a feature to customize the "Field is not optional" error message for each form field with the `nonOptionalErrorMsg` prop.

Following is an example of how to use above features.

```tsx
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "select-dropdown",
label: "Select Option",
getDefaultValue: () => "option 2",
nonOptionalErrorMsg: "Select dropdown is required",
inputComponent: ({ value, name, onChange }) => (
<select
value={value}
name={name}
onChange={(e) => onChange(e.target.value)}
placeholder="Select Option">
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
),
},
],
},
},
});

ThirdPartyEmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "terms",
label: "",
optional: false,
getDefaultValue: () => "true",
nonOptionalErrorMsg: "You must accept the terms and conditions",
inputComponent: ({ name, onChange, value }) => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "left",
}}>
<input
value={value}
checked={value === "true"}
name={name}
type="checkbox"
onChange={(e) => onChange(e.target.checked.toString())}></input>
<span style={{ marginLeft: 5 }}>I agree to the terms and conditions</span>
</div>
),
},
],
},
},
});
```

## [0.35.6] - 2023-10-16

### Test changes

- Updated test expectations to match fix in the node behaviour of the emailVerifyGET endpoint

## [0.35.5] - 2023-10-06

### Changes
Expand Down
2 changes: 1 addition & 1 deletion docs/classes/index.default.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_authRecipe.default.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_emailpassword.default.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_emailverification.default.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_multitenancy.default.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_passwordless.default.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_recipeModule.default.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_session.BooleanClaim.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_session.PrimitiveArrayClaim.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_session.PrimitiveClaim.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_session.default.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.ActiveDirectory.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.Apple.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.Bitbucket.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.BoxySAML.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.Discord.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.Facebook.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.Github.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.Gitlab.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.Google.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.GoogleWorkspaces.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.LinkedIn.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.Okta.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.Twitter.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdparty.default.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdpartyemailpassword.default.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_thirdpartypasswordless.default.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/classes/recipe_userroles.default.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/modules/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/modules/recipe_emailpassword.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/modules/recipe_emailverification.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/modules/recipe_multitenancy.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/modules/recipe_passwordless.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/modules/recipe_session.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/modules/recipe_thirdparty.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/modules/recipe_thirdpartyemailpassword.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/modules/recipe_thirdpartypasswordless.html

Large diffs are not rendered by default.

223 changes: 218 additions & 5 deletions examples/for-tests/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,167 @@ const formFields = [
},
];

const formFieldsWithDefault = [
{
id: "country",
label: "Your Country",
placeholder: "Where do you live?",
optional: true,
getDefaultValue: () => "India",
},
{
id: "select-dropdown",
label: "Select Option",
getDefaultValue: () => "option 2",
inputComponent: ({ value, name, onChange }) => (
<select value={value} name={name} onChange={(e) => onChange(e.target.value)}>
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
),
optional: true,
},
{
id: "terms",
label: "",
optional: false,
getDefaultValue: () => "true",
inputComponent: ({ name, onChange, value }) => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "left",
}}>
<input
value={value}
checked={value === "true"}
name={name}
type="checkbox"
onChange={(e) => onChange(e.target.checked.toString())}></input>
<span style={{ marginLeft: 5 }}>I agree to the terms and conditions</span>
</div>
),
validate: async (value) => {
if (value === "true") {
return undefined;
}
return "Please check Terms and conditions";
},
},
{
id: "email",
label: "Email",
getDefaultValue: () => "[email protected]",
},
{
id: "password",
label: "Password",
getDefaultValue: () => "fakepassword123",
},
];

const incorrectFormFields = [
{
id: "country",
label: "Your Country",
placeholder: "Where do you live?",
optional: true,
getDefaultValue: () => 23, // return should be a string
},
{
id: "select-dropdown",
label: "Select Dropdown",
getDefaultValue: "option 2", // should be function
inputComponent: ({ value, name, onChange }) => (
<select value={value} name={name} onChange={(e) => onChange(e.target.value)}>
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
),
optional: true,
},
{
// onChange accepts only string value, here we pass boolean
id: "terms",
label: "",
optional: false,
inputComponent: ({ name, onChange }) => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "left",
}}>
<input name={name} type="checkbox" onChange={(e) => onChange(e.target.checked)}></input>
<span style={{ marginLeft: 5 }}>I agree to the terms and conditions</span>
</div>
),
validate: async (value) => {
if (value === "true") {
return undefined;
}
return "Please check Terms and conditions";
},
},
{
id: "city",
label: "Your city",
optional: false,
nonOptionalErrorMsg: "", // empty string should throw error
},
];

const customFields = [
{
id: "select-dropdown",
label: "Select Dropdown",
nonOptionalErrorMsg: "Select dropdown is not an optional",
inputComponent: ({ value, name, onChange }) => (
<select value={value} name={name} onChange={(e) => onChange(e.target.value)}>
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
),
optional: true,
},
{
id: "terms",
label: " ",
optional: false,
nonOptionalErrorMsg: "You must accept the terms and conditions",
inputComponent: ({ name, onChange }) => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "left",
}}>
<input name={name} type="checkbox" onChange={(e) => onChange(e.target.checked.toString())}></input>
<span style={{ marginLeft: 5 }}>I agree to the terms and conditions</span>
</div>
),
validate: async (value) => {
if (value === "true") {
return undefined;
}
return "Please check Terms and conditions";
},
},
];

const testContext = getTestContext();

let recipeList = [
Expand Down Expand Up @@ -557,7 +718,51 @@ function getEmailVerificationConfigs({ disableDefaultUI }) {
});
}

function getEmailPasswordConfigs({ disableDefaultUI }) {
function getSignUpFormFields(formType) {
switch (formType) {
case "INCORRECT_FIELDS":
return incorrectFormFields;
case "INCORRECT_ONCHANGE":
return incorrectFormFields.filter(({ id }) => id === "terms");
case "INCORRECT_NON_OPTIONAL_ERROR_MSG":
return incorrectFormFields.filter(({ id }) => id === "city");
case "INCORRECT_GETDEFAULT":
return incorrectFormFields.filter(({ id }) => id === "country");
case "CUSTOM_FIELDS_WITH_DEFAULT_VALUES":
return formFieldsWithDefault;
case "CUSTOM_FIELDS":
return customFields;
default:
return formFields;
}
}

function getSignInFormFields(formType) {
switch (formType) {
case "DEFAULT_FIELDS":
return [
{
id: "email",
getDefaultValue: () => "[email protected]",
},
{
id: "password",
getDefaultValue: () => "fakepassword123",
},
];
case "FIELDS_WITH_NON_OPTIONAL_ERROR_MESSAGE":
return [
{
id: "email",
nonOptionalErrorMsg: "Please add email",
},
];
default:
return;
}
}

function getEmailPasswordConfigs({ disableDefaultUI, formFieldType }) {
return EmailPassword.init({
style: `
[data-supertokens~=container] {
Expand Down Expand Up @@ -637,12 +842,13 @@ function getEmailPasswordConfigs({ disableDefaultUI }) {
defaultToSignUp,
signInForm: {
style: theme,
formFields: getSignInFormFields(formFieldType.signIn),
},
signUpForm: {
style: theme,
privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
formFields,
formFields: getSignUpFormFields(formFieldType.signUp),
},
},
});
Expand Down Expand Up @@ -986,7 +1192,12 @@ function getThirdPartyConfigs({ staticProviderList, disableDefaultUI, thirdParty
});
}

function getThirdPartyEmailPasswordConfigs({ staticProviderList, disableDefaultUI, thirdPartyRedirectURL }) {
function getThirdPartyEmailPasswordConfigs({
staticProviderList,
disableDefaultUI,
thirdPartyRedirectURL,
formFieldType,
}) {
let providers = [
ThirdParty.Github.init(),
ThirdParty.Google.init(),
Expand Down Expand Up @@ -1165,9 +1376,11 @@ function getThirdPartyEmailPasswordConfigs({ staticProviderList, disableDefaultU
},
signInAndUpFeature: {
disableDefaultUI,
signInForm: {},
signInForm: {
formFields: getSignInFormFields(formFieldType.signIn),
},
signUpForm: {
formFields,
formFields: getSignUpFormFields(formFieldType.signUp),
privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
},
Expand Down
4 changes: 4 additions & 0 deletions examples/for-tests/src/testContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export function getTestContext() {
mockTenantId: localStorage.getItem("mockTenantId"),
clientType: localStorage.getItem("clientType") || undefined,
firstFactors: localStorage.getItem("firstFactors")?.split(", "),
formFieldType: {
signIn: localStorage.getItem("SIGNIN_SETTING_TYPE"),
signUp: localStorage.getItem("SIGNUP_SETTING_TYPE"),
},
};
return ret;
}
Expand Down
7 changes: 7 additions & 0 deletions lib/build/emailpassword-shared4.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 2a6ab14

Please sign in to comment.