diff --git a/src/dashboard/Data/Browser/ImportDialog.react.js b/src/dashboard/Data/Browser/ImportDialog.react.js index 78e4f2372f..6317dbeee8 100644 --- a/src/dashboard/Data/Browser/ImportDialog.react.js +++ b/src/dashboard/Data/Browser/ImportDialog.react.js @@ -34,7 +34,7 @@ export default class ImportDialog extends React.Component { this.setState({ startedImport: false, file: undefined })); }}> diff --git a/src/dashboard/Data/Browser/ImportRelationDialog.react.js b/src/dashboard/Data/Browser/ImportRelationDialog.react.js index 67604101c5..e77f9800f8 100644 --- a/src/dashboard/Data/Browser/ImportRelationDialog.react.js +++ b/src/dashboard/Data/Browser/ImportRelationDialog.react.js @@ -36,7 +36,7 @@ export default class ImportRelationDialog extends React.Component { {this.state.startedImport ? -
We are importing your data. You will be notified by e-mail once it is completed.
: null } +
We are importing your data. You will be notified by email once it is completed.
: null } {this.state.errorMessage ?
Import Request failed with the following error: "{ this.state.errorMessage }".
: null }
diff --git a/src/dashboard/DomainSettings/DomainSettings.react.js b/src/dashboard/DomainSettings/DomainSettings.react.js index cbb36dc13e..2a199bb810 100644 --- a/src/dashboard/DomainSettings/DomainSettings.react.js +++ b/src/dashboard/DomainSettings/DomainSettings.react.js @@ -24,9 +24,7 @@ import Fieldset from 'components/Fieldset/Fieldset.react'; import { amplitudeLogEvent } from 'lib/amplitudeEvents'; import B4aNotification from 'dashboard/Data/Browser/B4aNotification.react'; import browserStyles from 'dashboard/Data/Browser/Browser.scss'; -import StripeValidateCard from 'components/StripeValidateCard/StripeValidateCard.react'; import { Link } from 'react-router-dom'; -import back4app2 from 'lib/back4app2'; @withRouter class DomainSettings extends DashboardView { @@ -40,9 +38,12 @@ class DomainSettings extends DashboardView { domainSettingsError: null, isUserVerified: false, + emailVerified: false, + cardValidated: false, + isResendingVerificationEmail: false, + resendVerificationMessage: null, canChangeCustomDomain: false, canChangeSubdomain: false, - showCardValidation: true, subdomainName: '', currentSubdomain: '', @@ -96,10 +97,8 @@ class DomainSettings extends DashboardView { } async loadData() { - console.log("STATE", this.state); try { const response = await this.context.getCustomDomain(); - console.log("RESPONSE", response); this.setState({ domainSettings: response }); await this.loadHostSettings(response); } catch (error) { @@ -119,6 +118,10 @@ class DomainSettings extends DashboardView { let isActivated = false; let hasPermission = false; let isUserVerified = false; + const currentUser = AccountManager.currentUser(); + const verification = (currentUser && currentUser.verification) || {}; + const emailVerified = !!verification.emailVerified; + const cardValidated = !!verification.cardValidation; if (domains && domains.length > 0) { customDomainArray = domains; @@ -141,8 +144,6 @@ class DomainSettings extends DashboardView { hasPermission = (!response.featuresPermission || response.featuresPermission.webHostLiveQuery === 'Write'); - console.log("response", createdAt); - if (response && ((appHostSettings.serverURL && appHostSettings.activated) || (createdAt && ((new Date() - new Date(createdAt)) > (6 * 30 * 24 * 60 * 60 * 1000))))) { isUserVerified = true; } @@ -152,15 +153,11 @@ class DomainSettings extends DashboardView { const plan = await this.context.getAppPlanData(); if (plan && plan.planName && (plan.planName.indexOf('Free') < 0) && (plan.planName.indexOf('Public') < 0)) { isUserVerified = true; - } else { - const currentUser = AccountManager.currentUser(); - if (currentUser && currentUser.verification.cardValidation) { - isUserVerified = true; - } + } else if (emailVerified && cardValidated) { + isUserVerified = true; } } catch (planError) { - const currentUser = AccountManager.currentUser(); - if (currentUser && currentUser.verification.cardValidation) { + if (emailVerified && cardValidated) { isUserVerified = true; } } @@ -168,6 +165,8 @@ class DomainSettings extends DashboardView { this.setState({ isUserVerified, + emailVerified, + cardValidated, subdomainName, currentSubdomain, @@ -296,17 +295,109 @@ class DomainSettings extends DashboardView { } } - async verifyUser() { + async handleResendEmailVerification() { + if (this.state.isResendingVerificationEmail) { + return; + } + + this.setState({ + isResendingVerificationEmail: true, + resendVerificationMessage: null, + }); + try { - const user = await back4app2.me(); - if (user) { - this.setState({ isUserVerified: true }); - } - } catch (e) { - console.log('user validation failed!') + const result = await this.context.resendEmailVerification(); + this.setState({ + isResendingVerificationEmail: false, + resendVerificationMessage: { + type: 'success', + text: typeof result === 'string' && result.trim() + ? result + : 'Verification email sent.', + }, + }); + } catch (err) { + this.setState({ + isResendingVerificationEmail: false, + resendVerificationMessage: { + type: 'error', + text: typeof err === 'string' && err.trim() + ? err + : (err && err.message) || 'Failed to resend verification email', + }, + }); } } + renderVerificationRequired() { + const { emailVerified, cardValidated, isResendingVerificationEmail, resendVerificationMessage } = this.state; + + return ( + <> + {!emailVerified && ( +
+ Please verify your email to enable this feature.{' '} + + {resendVerificationMessage && ( +
+ {resendVerificationMessage.text} +
+ )} +
+ )} + + {!cardValidated && ( +
+ + } + input={ +
+ +
+ } + theme={Field.Theme.BLUE} + /> +
+ )} + + ); + } + getDisplayContent() { let content = null; @@ -527,6 +618,8 @@ class DomainSettings extends DashboardView { {this.state.errorCustomDomain &&
{this.state.errorCustomDomain}
} + } else { + content = this.renderVerificationRequired(); } return ( diff --git a/src/dashboard/Notification/EmailVerification.react.js b/src/dashboard/Notification/EmailVerification.react.js index 0efa655862..a4d6c5f2e8 100644 --- a/src/dashboard/Notification/EmailVerification.react.js +++ b/src/dashboard/Notification/EmailVerification.react.js @@ -21,7 +21,7 @@ import { amplitudeLogEvent } from 'lib/amplitudeEvents'; const DEFAULT_VERIFICATION_BODY = 'Hi,\n\n' + - 'You are being asked to confirm the e-mail address *|email|* with *|appname|*\n\n' + + 'You are being asked to confirm the email address *|email|* with *|appname|*\n\n' + 'Click here to confirm it:\n' + '*|link|*'; @@ -30,7 +30,7 @@ const DEFAULT_FIELDS = { preventLoginWithUnverifiedEmail: false, replyTo: 'no-reply@b4a.app', displayName: '', - verificationEmailSubject: 'Please verify your e-mail for *|appname|*', + verificationEmailSubject: 'Please verify your email for *|appname|*', verificationEmailBody: DEFAULT_VERIFICATION_BODY, }; @@ -379,7 +379,7 @@ class EmailVerification extends DashboardView { input={
@@ -546,7 +546,7 @@ class EmailVerification extends DashboardView { input={
canEditTemplateFields && trackSetField('verificationEmailSubject', getInputValue(valueOrEvent)) diff --git a/src/dashboard/ServerURLLiveQuery/ServerURLLiveQuery.react.js b/src/dashboard/ServerURLLiveQuery/ServerURLLiveQuery.react.js index 49eb02c9d8..723425246d 100644 --- a/src/dashboard/ServerURLLiveQuery/ServerURLLiveQuery.react.js +++ b/src/dashboard/ServerURLLiveQuery/ServerURLLiveQuery.react.js @@ -45,6 +45,10 @@ class ServerURLLiveQuery extends DashboardView { loadingError: null, isUserVerified: false, + emailVerified: false, + cardValidated: false, + isResendingVerificationEmail: false, + resendVerificationMessage: null, hasPermission: true, isActivated: false, @@ -182,6 +186,10 @@ class ServerURLLiveQuery extends DashboardView { let activated = false; let isActivated = false; let isUserVerified = false; + const currentUser = AccountManager.currentUser(); + const verification = (currentUser && currentUser.verification) || {}; + const emailVerified = !!verification.emailVerified; + const cardValidated = !!verification.cardValidation; const schemasChoose = {}; let activatedLiveQuery = {}; let statusLiveQuery = false; @@ -224,15 +232,11 @@ class ServerURLLiveQuery extends DashboardView { plan.planName.indexOf('Free') < 0 && plan.planName.indexOf('Public') < 0) { isUserVerified = true; - } else { - const currentUser = AccountManager.currentUser(); - if (currentUser && currentUser.verification && currentUser.verification.cardValidation) { - isUserVerified = true; - } + } else if (emailVerified && cardValidated) { + isUserVerified = true; } } catch (planError) { - const currentUser = AccountManager.currentUser(); - if (currentUser && currentUser.verification && currentUser.verification.cardValidation) { + if (emailVerified && cardValidated) { isUserVerified = true; } } @@ -240,6 +244,8 @@ class ServerURLLiveQuery extends DashboardView { this.setState({ isUserVerified, + emailVerified, + cardValidated, hasPermission, isActivated, currentSubdomain, @@ -266,6 +272,116 @@ class ServerURLLiveQuery extends DashboardView { return domain; } + async handleResendEmailVerification() { + if (this.state.isResendingVerificationEmail) { + return; + } + + this.setState({ + isResendingVerificationEmail: true, + resendVerificationMessage: null, + }); + + try { + const result = await this.context.resendEmailVerification(); + this.setState({ + isResendingVerificationEmail: false, + resendVerificationMessage: { + type: 'success', + text: typeof result === 'string' && result.trim() + ? result + : 'Verification email sent.', + }, + }); + } catch (err) { + this.setState({ + isResendingVerificationEmail: false, + resendVerificationMessage: { + type: 'error', + text: typeof err === 'string' && err.trim() + ? err + : (err && err.message) || 'Failed to resend verification email', + }, + }); + } + } + + renderVerificationRequired() { + const { emailVerified, cardValidated, isResendingVerificationEmail, resendVerificationMessage } = this.state; + + return ( +
+
+
Server URL and Live Query
+
+ In this section, you can enable a custom Server URL that can be used for real-time database. +
+ + {!emailVerified && ( +
+ Please verify your email to enable this feature.{' '} + + {resendVerificationMessage && ( +
+ {resendVerificationMessage.text} +
+ )} +
+ )} + + {!cardValidated && ( +
+ + } + input={ + + } + theme={Field.Theme.BLUE} + /> +
+ )} +
+
+ ); + } + renderToolbar() { return ( @@ -462,42 +578,7 @@ class ServerURLLiveQuery extends DashboardView {
); } else if (!this.state.isUserVerified) { - content = ( -
-
-
Server URL and Live Query
-
- In this section, you can enable a custom Server URL that can be used for real-time database. -
-
- - } - input={ - - } - theme={Field.Theme.BLUE} - /> -
-
-
- ); + content = this.renderVerificationRequired(); } else { const { initialFields, hasPermission } = this.state;