Merge pull request #15992 from overleaf/ab-group-sso-test-flow-1

[web] Group SSO multi-step modal and test flow

GitOrigin-RevId: 343a20ef494276e65b35d1ee070c28d94617ea61
This commit is contained in:
Jessica Lawshe 2023-12-06 07:55:52 -06:00 committed by Copybot
parent 22aa7a17b2
commit 3499ebe939
7 changed files with 238 additions and 41 deletions

View file

@ -5,10 +5,10 @@ const SSOConfigSchema = new Schema(
{
entryPoint: { type: String, required: true },
certificates: { type: Array, default: [''], required: true },
signatureAlgorithm: { type: String, required: true },
userIdAttribute: { type: String, required: true },
userFirstNameAttribute: { type: String },
userLastNameAttribute: { type: String },
validated: { type: Boolean, default: false },
enabled: { type: Boolean, default: false },
},

View file

@ -128,7 +128,6 @@
"category_operators": "",
"category_relations": "",
"center": "",
"certificate": "",
"change": "",
"change_currency": "",
"change_or_cancel-cancel": "",
@ -286,6 +285,7 @@
"download": "",
"download_pdf": "",
"download_zip_file": "",
"draft_sso_configuration": "",
"drag_here": "",
"drag_here_paste_an_image_or": "",
"dropbox_checking_sync_status": "",
@ -310,7 +310,6 @@
"each_user_will_have_access_to": "",
"easily_manage_your_project_files_everywhere": "",
"edit": "",
"edit_configuration": "",
"edit_dictionary": "",
"edit_dictionary_empty": "",
"edit_dictionary_remove": "",
@ -469,6 +468,7 @@
"group_managed_by_group_administrator": "",
"group_plan_tooltip": "",
"group_plan_with_name_tooltip": "",
"group_sso_configuration_idp_metadata": "",
"group_subscription": "",
"have_an_extra_backup": "",
"have_more_days_to_try": "",
@ -753,6 +753,7 @@
"new_to_latex_look_at": "",
"newsletter": "",
"newsletter_onboarding_accept": "",
"next": "",
"next_payment_of_x_collectected_on_y": "",
"no_actions": "",
"no_borders": "",
@ -882,6 +883,7 @@
"primarily_work_study_question_nonprofit_ngo": "",
"primarily_work_study_question_other": "",
"primarily_work_study_question_university_school": "",
"primary_certificate": "",
"priority_support": "",
"private": "",
"problem_talking_to_publishing_service": "",
@ -952,6 +954,7 @@
"recurly_email_update_needed": "",
"recurly_email_updated": "",
"redirect_to_editor": "",
"redirect_url": "",
"reduce_costs_group_licenses": "",
"reference_error_relink_hint": "",
"reference_managers": "",
@ -1091,6 +1094,7 @@
"session_expired_redirecting_to_login": "",
"sessions": "",
"set_color": "",
"set_up_sso": "",
"settings": "",
"setup_another_account_under_a_personal_email_address": "",
"share": "",
@ -1120,6 +1124,7 @@
"single_sign_on_sso": "",
"skip": "",
"something_not_right": "",
"something_went_wrong": "",
"something_went_wrong_loading_pdf_viewer": "",
"something_went_wrong_processing_the_request": "",
"something_went_wrong_rendering_pdf": "",
@ -1136,12 +1141,12 @@
"sso_config_prop_help_certificate": "",
"sso_config_prop_help_first_name": "",
"sso_config_prop_help_last_name": "",
"sso_config_prop_help_redirect_url": "",
"sso_config_prop_help_signature_algorithm": "",
"sso_config_prop_help_user_entry_point": "",
"sso_config_prop_help_user_id": "",
"sso_configuration": "",
"sso_configuration_created": "",
"sso_configuration_updated": "",
"sso_configuration_not_finalized": "",
"sso_configuration_saved": "",
"sso_explanation": "",
"sso_is_disabled": "",
"sso_is_disabled_explanation_1": "",
@ -1156,6 +1161,9 @@
"sso_link_your_group_uses_sso": "",
"sso_logs": "",
"sso_not_active": "",
"sso_test_interstitial_info_1": "",
"sso_test_interstitial_info_2": "",
"sso_test_interstitial_title": "",
"start_a_free_trial": "",
"start_by_adding_your_email": "",
"start_free_trial": "",
@ -1215,7 +1223,9 @@
"template_title_taken_from_project_title": "",
"templates": "",
"terminated": "",
"test": "",
"test_configuration": "",
"test_configuration_successful": "",
"tex_live_version": "",
"thank_you_exclamation": "",
"thanks_for_subscribing": "",
@ -1387,6 +1397,7 @@
"user_id_attribute": "",
"user_last_name_attribute": "",
"user_sessions": "",
"valid_sso_configuration": "",
"validation_issue_entry_description": "",
"vat": "",
"vat_number": "",
@ -1399,10 +1410,12 @@
"view_hub_subtext": "",
"view_in_template_gallery": "",
"view_invitation": "",
"view_less": "",
"view_logs": "",
"view_metrics": "",
"view_metrics_commons_subtext": "",
"view_metrics_group_subtext": "",
"view_more": "",
"view_pdf": "",
"view_your_invoices": "",
"viewing_x": "",
@ -1449,6 +1462,7 @@
"you_are_on_a_paid_plan_contact_support_to_find_out_more": "",
"you_are_on_x_plan_as_a_confirmed_member_of_institution_y": "",
"you_are_on_x_plan_as_member_of_group_subscription_y_administered_by_z": "",
"you_can_now_enable_sso": "",
"you_can_now_log_in_sso": "",
"you_dont_have_any_repositories": "",
"you_have_added_x_of_group_size_y": "",

View file

@ -110,8 +110,39 @@ h3.group-settings-title {
}
.sso-config-info {
padding: 12px 0;
.sso-config-info-header {
display: flex;
justify-content: space-between;
gap: @margin-xs;
padding: 0 @padding-base-horizontal 15px @padding-base-horizontal;
border-bottom: 1px solid @neutral-20;
margin-bottom: 15px;
flex-wrap: wrap;
.status-label {
font-size: @font-size-small;
border-radius: 4px;
padding: 2px 4px;
margin-top: 4px;
flex-shrink: 0;
&.status-label-valid {
background-color: @ol-green;
color: @neutral-10;
}
&.status-label-draft {
background-color: @neutral-20;
color: @neutral-90;
}
}
}
.sso-config-info-section {
margin-bottom: @margin-md;
padding: 0 @padding-base-horizontal;
}
.sso-config-info-label {
@ -124,13 +155,105 @@ h3.group-settings-title {
word-break: break-word;
}
.sso-config-info-footer {
display: flex;
justify-content: flex-end;
gap: @margin-xs;
}
p {
margin-bottom: @margin-xs;
}
}
.sso-config-modal-content {
.sso-config-interstitial-title,
.sso-config-test-result-title {
font-family: Lato, sans-serif;
font-size: 20px;
font-weight: bold;
text-align: center;
}
.sso-config-modal-icon-wrapper {
text-align: center;
margin-top: 8px;
.sso-config-interstitial-icon,
.sso-config-test-result-icon,
.sso-config-test-error-icon {
font-size: 32px;
width: 80px;
height: 80px;
padding: 24px;
border-radius: 999px;
gap: 8px;
}
.sso-config-interstitial-icon {
background-color: @neutral-10;
}
.sso-config-test-result-icon {
background-color: @green-10;
color: @ol-green;
}
.sso-config-test-error-icon {
background-color: @red-10;
color: @red-50;
}
}
.sso-config-test-result-title {
font-family: Lato, sans-serif;
font-size: 20px;
font-weight: bold;
text-align: center;
}
.has-feedback {
.form-control {
padding-right: 0;
}
}
}
.certificate-wrapper {
display: flex;
&.certificate-full {
flex-wrap: wrap;
}
.view-more {
flex-grow: 1;
flex-shrink: 0;
}
}
.certificate {
font-family: Courier, monospace;
.certificate-truncated & {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
display: inline-block;
flex-grow: 4;
}
.certificate-full & {
word-break: break-all;
.break {
flex-basis: 100%;
height: 0;
}
}
}
.certificate-form-row {
display: flex;
.certificate-input {
flex-grow: 11;
}
.certificate-delete {
flex-grow: 1;
flex-shrink: 0;
}
}

View file

@ -51,7 +51,7 @@
"activating": "Activating",
"activation_token_expired": "Your activation token has expired, you will need to get another one sent to you.",
"add": "Add",
"add_additional_certificate": "Add additional certificate",
"add_additional_certificate": "Add another certificate",
"add_affiliation": "Add Affiliation",
"add_another_address_line": "Add another address line",
"add_another_email": "Add another email",
@ -425,6 +425,7 @@
"download": "Download",
"download_pdf": "Download PDF",
"download_zip_file": "Download .zip file",
"draft_sso_configuration": "Draft SSO configuration",
"drag_here": "drag here",
"drag_here_paste_an_image_or": "Drag here, paste an image, or ",
"drop_files_here_to_upload": "Drop files here to upload",
@ -459,7 +460,6 @@
"ease_of_use": " Ease of Use",
"easily_manage_your_project_files_everywhere": "Easily manage your project files, everywhere",
"edit": "Edit",
"edit_configuration": "Edit configuration",
"edit_dictionary": "Edit Dictionary",
"edit_dictionary_empty": "Your custom dictionary is empty.",
"edit_dictionary_remove": "Remove from dictionary",
@ -730,6 +730,7 @@
"group_plan_with_name_tooltip": "You are on the __plan__ plan as a member of a group subscription, __groupName__. Click to find out how to make the most of your Overleaf premium features.",
"group_plans": "Group Plans",
"group_professional": "Group Professional",
"group_sso_configuration_idp_metadata": "The information provided here comes from your Identity Provider (IdP). This is often referred to as its SAML metadata. For some IdPs, you must configure Overleaf as a Service Provider in order to obtain the data required to fill out this form. Please see <0>our documentation</0> for more guidance.",
"group_standard": "Group Standard",
"group_subscription": "Group Subscription",
"groups": "Groups",
@ -1145,6 +1146,7 @@
"newsletter_info_title": "Newsletter Preferences",
"newsletter_info_unsubscribed": "You are currently <0>unsubscribed</0> to the __appName__ newsletter.",
"newsletter_onboarding_accept": "Yes, Id like to get relevant help resources, news, and feature updates.",
"next": "Next",
"next_payment_of_x_collectected_on_y": "The next payment of <0>__paymentAmmount__</0> will be collected on <1>__collectionDate__</1>.",
"nl": "Dutch",
"no": "Norwegian",
@ -1347,6 +1349,7 @@
"primarily_work_study_question_nonprofit_ngo": "Nonprofit or NGO",
"primarily_work_study_question_other": "Other",
"primarily_work_study_question_university_school": "University or school",
"primary_certificate": "Primary certificate",
"primary_email_check_question": "Is <0>__email__</0> still your email address?",
"priority_support": "Priority support",
"priority_support_info": "Our helpful Support team will prioritise and escalate your support requests where necessary.",
@ -1436,6 +1439,7 @@
"recurly_email_update_needed": "Your billing email address is currently <0>__recurlyEmail__</0>. If needed you can update your billing address to <1>__userEmail__</1>.",
"recurly_email_updated": "Your billing email address was successfully updated",
"redirect_to_editor": "Redirect to editor",
"redirect_url": "Redirect URL",
"redirecting": "Redirecting",
"reduce_costs_group_licenses": "You can cut down on paperwork and reduce costs with our discounted group licenses.",
"refer_a_friend": "Refer a friend",
@ -1630,6 +1634,7 @@
"set_color": "set color",
"set_new_password": "Set new password",
"set_password": "Set Password",
"set_up_sso": "Set up SSO",
"settings": "Settings",
"setup_another_account_under_a_personal_email_address": "Set up another Overleaf account under a personal email address.",
"share": "Share",
@ -1669,6 +1674,7 @@
"sl_gives_you_free_stuff_see_progress_below": "When someone starts using __appName__ after your recommendation well give you some <strong>free stuff</strong> to say thanks! Check your progress below.",
"sl_included_history_of_changes_blurb": "__appName__ includes a history of all of your changes so you can see exactly who changed what, and when. This makes it extremely easy to keep up to date with any progress made by your collaborators and allows you to review recent work.",
"something_not_right": "Somethings not right",
"something_went_wrong": "Something went wrong",
"something_went_wrong_canceling_your_subscription": "Something went wrong canceling your subscription. Please contact support.",
"something_went_wrong_loading_pdf_viewer": "Something went wrong loading the PDF viewer. This might be caused by issues like <0>temporary network problems</0> or an <0>outdated web browser</0>. Please follow the <1>troubleshooting steps for access, loading and display problems</1>. If the issue persists, please <2>let us know</2>.",
"something_went_wrong_processing_the_request": "Something went wrong processing the request",
@ -1689,14 +1695,14 @@
"sso_account_already_linked": "Account already linked to another __appName__ user",
"sso_active": "SSO active",
"sso_config_prop_help_certificate": "Base64 encoded certificate without whitespace",
"sso_config_prop_help_first_name": "Property in SAML assertion to use for first name",
"sso_config_prop_help_last_name": "Property in SAML assertion to use for last name",
"sso_config_prop_help_first_name": "The SAML attribute that specifies the users first name",
"sso_config_prop_help_last_name": "The SAML attribute that specifies the users last name",
"sso_config_prop_help_redirect_url": "The single sign-on redirect URL provided by your IdP (sometimes called the single sign-on service HTTP-redirect location)",
"sso_config_prop_help_signature_algorithm": "Base64 encoded certificate without whitespace",
"sso_config_prop_help_user_entry_point": "URL for SAML SSO redirect flow",
"sso_config_prop_help_user_id": "Property in SAML assertion to use for unique id",
"sso_config_prop_help_user_id": "The SAML attribute provided by your IdP that identifies each user",
"sso_configuration": "SSO configuration",
"sso_configuration_created": "SSO configuration has been saved",
"sso_configuration_updated": "SSO configuration was updated successfully",
"sso_configuration_not_finalized": "Your configuration has not been finalized.",
"sso_configuration_saved": "SSO configuration has been saved",
"sso_explanation": "Set up single sign-on for your group. This sign in method will be optional for group members unless Managed Users is enabled. <0>Learn more about Overleaf Group SSO</0>.",
"sso_integration": "SSO integration",
"sso_integration_info": "Overleaf offers a standard SAML-based Single Sign On integration.",
@ -1714,6 +1720,9 @@
"sso_logs": "SSO Logs",
"sso_not_active": "SSO not active",
"sso_not_linked": "You have not linked your account to __provider__. Please log in to your account another way and link your __provider__ account via your account settings.",
"sso_test_interstitial_info_1": "<0>Before starting this test</0>, please ensure youve <1>configured Overleaf as a Service Provider in your IdP</1>, and authorized access to the Overleaf service.",
"sso_test_interstitial_info_2": "Clicking <0>Test configuration</0> will redirect you to your IdPs login screen. <1>Read our documentation</1> for full details of what happens during the test. And check our <2>SSO troubleshooting advice</2> if you get stuck.",
"sso_test_interstitial_title": "Lets test your SSO configuration",
"sso_title": "Single sign-on",
"sso_user_denied_access": "Cannot log in because __appName__ was not granted access to your __provider__ account. Please try again.",
"standard": "Standard",
@ -1801,7 +1810,9 @@
"templates_page_title": "Templates - Journals, CVs, Presentations, Reports and More",
"terminated": "Compilation cancelled",
"terms": "Terms",
"test": "Test",
"test_configuration": "Test configuration",
"test_configuration_successful": "Test configuration successful",
"tex_live_version": "TeX Live version",
"thank_you": "Thank you!",
"thank_you_email_confirmed": "Thank you, your email is now confirmed",
@ -2016,15 +2027,16 @@
"user_already_added": "User already added",
"user_deletion_error": "Sorry, something went wrong deleting your account. Please try again in a minute.",
"user_deletion_password_reset_tip": "If you cannot remember your password, or if you are using Single-Sign-On with another provider to sign in (such as Twitter or Google), please <0>reset your password</0> and try again.",
"user_first_name_attribute": "User First Name Attribute",
"user_id_attribute": "User ID Attribute",
"user_first_name_attribute": "User first name attribute",
"user_id_attribute": "Unique identifier",
"user_is_not_part_of_group": "User is not part of group",
"user_last_name_attribute": "User Last Name Attribute",
"user_last_name_attribute": "User last name attribute",
"user_management": "User management",
"user_management_info": "Group plan admins have access to an admin panel where users can be added and removed easily. For site-wide plans, users are automatically upgraded when they register or add their email address to Overleaf (domain-based enrollment or SSO).",
"user_not_found": "User not found",
"user_sessions": "User Sessions",
"user_wants_you_to_see_project": "__username__ would like you to join __projectname__",
"valid_sso_configuration": "Valid SSO configuration",
"validation_issue_entry_description": "A validation issue which prevented this project from compiling",
"vat": "VAT",
"vat_number": "VAT Number",
@ -2038,10 +2050,12 @@
"view_hub_subtext": "Access and download subscription statistics and a list of users",
"view_in_template_gallery": "View it in the template gallery",
"view_invitation": "View Invitation",
"view_less": "View less",
"view_logs": "View logs",
"view_metrics": "View metrics",
"view_metrics_commons_subtext": "Monitor and download usage metrics for your Commons subscription",
"view_metrics_group_subtext": "Monitor and download usage metrics for your group subscription",
"view_more": "View more",
"view_pdf": "View PDF",
"view_source": "View Source",
"view_templates": "View templates",
@ -2107,6 +2121,7 @@
"you_are_on_a_paid_plan_contact_support_to_find_out_more": "Youre on an __appName__ Paid plan. <0>Contact support</0> to find out more.",
"you_are_on_x_plan_as_a_confirmed_member_of_institution_y": "You are on our <0>__planName__</0> plan as a <1>confirmed member</1> of <1>__institutionName__</1>",
"you_are_on_x_plan_as_member_of_group_subscription_y_administered_by_z": "You are on our <0>__planName__</0> plan as a <1>member</1> of the group subscription <1>__groupName__</1> administered by <1>__adminEmail__</1>",
"you_can_now_enable_sso": "You can now enable SSO on your Group settings page.",
"you_can_now_log_in_sso": "You can now log in through your institution and if eligible you will receive <0>__appName__ Professional features</0>.",
"you_can_opt_in_and_out_of_overleaf_labs_at_any_time_on_this_page": "You can <0>opt in and out</0> of Overleaf Labs at any time on this page",
"you_can_opt_in_and_out_of_the_program_at_any_time_on_this_page": "You can <0>opt in and out</0> of the program at any time on this page",
@ -2122,7 +2137,7 @@
"you_introed_high_number": " Youve introduced <0>__numberOfPeople__</0> people to __appName__. Good job!",
"you_introed_small_number": " Youve introduced <0>__numberOfPeople__</0> person to __appName__. Good job, but can you get some more?",
"you_may_be_able_to_fix_issues_to_speed_up_the_compile": "You may be able to fix issues to <0>speed up the compile</0>.",
"you_need_to_configure_your_sso_settings": "You need to configure your SSO settings before enabling SSO",
"you_need_to_configure_your_sso_settings": "You need to configure and test your SSO settings before enabling SSO",
"you_not_introed_anyone_to_sl": "Youve not introduced anyone to __appName__ yet. Get sharing!",
"you_plus_1": "You + 1",
"you_plus_10": "You + 10",

View file

@ -1,9 +1,12 @@
import GroupSettingsSSORoot from '../../../../../../modules/group-settings/frontend/js/components/sso/group-settings-sso-root'
import { SSOConfigurationProvider } from '../../../../../../modules/group-settings/frontend/js/context/sso-configuration-context'
function GroupSettingsSSOComponent() {
return (
<div style={{ padding: '25px', width: '600px' }}>
<GroupSettingsSSORoot managedUsersEnabled />
<SSOConfigurationProvider>
<GroupSettingsSSORoot />
</SSOConfigurationProvider>
</div>
)
}
@ -41,14 +44,58 @@ describe('GroupSettingsSSO', function () {
})
})
it('renders with sso configuration', function () {
it('renders with sso configuration not validated', function () {
cy.intercept('GET', `/manage/groups/${GROUP_ID}/settings/sso`, {
statusCode: 200,
body: {
entryPoint: 'entrypoint',
certificates: ['cert1', 'cert2'],
signatureAlgorithm: 'sha1',
userIdAttribute: 'email',
enabled: false,
validated: false,
},
}).as('sso')
cy.mount(<GroupSettingsSSOComponent />)
cy.wait('@sso')
cy.get('.switch-input').within(() => {
cy.get('.invisible-input').should('not.be.checked')
cy.get('.invisible-input').should('be.disabled')
})
})
it('renders with sso configuration validated and not enabled', function () {
cy.intercept('GET', `/manage/groups/${GROUP_ID}/settings/sso`, {
statusCode: 200,
body: {
entryPoint: 'entrypoint',
certificates: ['cert1', 'cert2'],
userIdAttribute: 'email',
validated: true,
enabled: false,
},
}).as('sso')
cy.mount(<GroupSettingsSSOComponent />)
cy.wait('@sso')
cy.get('.switch-input').within(() => {
cy.get('.invisible-input').should('not.be.checked')
cy.get('.invisible-input').should('not.be.disabled')
})
})
it('renders with sso configuration validated and enabled', function () {
cy.intercept('GET', `/manage/groups/${GROUP_ID}/settings/sso`, {
statusCode: 200,
body: {
entryPoint: 'entrypoint',
certificates: ['cert1', 'cert2'],
userIdAttribute: 'email',
validated: true,
enabled: true,
},
}).as('sso')
@ -63,15 +110,15 @@ describe('GroupSettingsSSO', function () {
})
})
it('updates the configuration, and checks the success message', function () {
it('updates the configuration, and checks the draft configuration message', function () {
cy.intercept('GET', `/manage/groups/${GROUP_ID}/settings/sso`, {
statusCode: 200,
body: {
entryPoint: 'entrypoint',
certificates: ['cert'],
signatureAlgorithm: 'sha1',
userIdAttribute: 'email',
enabled: true,
validated: true,
enabled: false,
},
}).as('sso')
@ -80,8 +127,8 @@ describe('GroupSettingsSSO', function () {
body: {
entryPoint: 'entrypoint',
certificates: ['certi'],
signatureAlgorithm: 'sha1',
userIdAttribute: 'email',
validated: false,
enabled: false,
},
}).as('ssoUpdated')
@ -91,15 +138,15 @@ describe('GroupSettingsSSO', function () {
cy.wait('@sso')
cy.get('.switch-input').within(() => {
cy.get('.invisible-input').should('be.checked')
cy.get('.invisible-input').should('not.be.checked')
cy.get('.invisible-input').should('not.be.disabled')
})
cy.findByRole('button', { name: 'View configuration' }).click()
cy.findByRole('button', { name: 'Edit configuration' }).click()
cy.findByRole('button', { name: 'Save' }).click()
cy.findByRole('button', { name: 'Edit' }).click()
cy.findByRole('button', { name: 'Next' }).click()
cy.wait('@ssoUpdated')
cy.findByText('SSO configuration was updated successfully')
cy.findByText('Your configuration has not been finalized.')
})
describe('sso enable modal', function () {
@ -109,7 +156,6 @@ describe('GroupSettingsSSO', function () {
body: {
entryPoint: 'entrypoint',
certificates: ['cert'],
signatureAlgorithm: 'sha1',
userIdAttribute: 'email',
enabled: false,
},
@ -150,8 +196,8 @@ describe('GroupSettingsSSO', function () {
body: {
entryPoint: 'entrypoint',
certificates: ['cert'],
signatureAlgorithm: 'sha1',
userIdAttribute: 'email',
validated: true,
enabled: true,
},
}).as('sso')
@ -177,8 +223,8 @@ describe('GroupSettingsSSO', function () {
body: {
entryPoint: 'entrypoint',
certificates: ['cert'],
signatureAlgorithm: 'sha1',
userIdAttribute: 'email',
validated: true,
enabled: true,
},
}).as('sso')
@ -220,8 +266,8 @@ describe('GroupSettingsSSO', function () {
body: {
entryPoint: 'entrypoint',
certificates: ['cert'],
signatureAlgorithm: 'sha1',
userIdAttribute: 'email',
validated: true,
enabled: false,
},
}).as('sso')

View file

@ -27,7 +27,6 @@ describe('GroupSSOHandler', function () {
this.ssoConfigData = {
entryPoint: 'https://example.com/saml',
certificates: ['abc'],
signatureAlgorithm: 'sha256',
userIdAttribute: 'nameId',
enabled: true,
}

View file

@ -1,9 +1,9 @@
export type SSOConfig = {
entryPoint?: string
certificates: (string | undefined)[]
signatureAlgorithm: 'sha1' | 'sha256' | 'sha512'
userIdAttribute?: string
userFirstNameAttribute?: string
userLastNameAttribute?: string
validated?: boolean
enabled?: boolean
}