diff --git a/.env.example b/.env.example
index a98011bb3d..6dfdfab187 100644
--- a/.env.example
+++ b/.env.example
@@ -57,4 +57,9 @@ APPSMITH_MAIL_SMTP_TLS_ENABLED=
#APPSMITH_SENTRY_ENVIRONMENT=
# Configure cloud services
-# APPSMITH_CLOUD_SERVICES_BASE_URL="https://release-cs.appsmith.com"
\ No newline at end of file
+# APPSMITH_CLOUD_SERVICES_BASE_URL="https://release-cs.appsmith.com"
+
+# Google Recaptcha Config
+APPSMITH_RECAPTCHA_SITE_KEY=
+APPSMITH_RECAPTCHA_SECRET_KEY=
+APPSMITH_RECAPTCHA_ENABLED=
\ No newline at end of file
diff --git a/app.json b/app.json
index d6bf73c26b..1a1fb89536 100644
--- a/app.json
+++ b/app.json
@@ -98,6 +98,21 @@
"value": "",
"required": false
},
+ "APPSMITH_RECAPTCHA_SITE_KEY": {
+ "description" : "Google reCAPTCHA v3 site key, it is required if you wish to enable protection against spam/abusive users. Read more at: https://developers.google.com/recaptcha/docs/v3",
+ "value": "",
+ "required": false
+ },
+ "APPSMITH_RECAPTCHA_SECRET_KEY": {
+ "description" : "Google reCAPTCHA v3 verification secret key, it is required if you wish to enable spam protection in your backend server.",
+ "value": "",
+ "required": false
+ },
+ "APPSMITH_RECAPTCHA_ENABLED": {
+ "description" : "Boolean config to enable or disable Google reCAPTCHA v3 verification feature. If set to true, both site key and secret key should be provided.",
+ "value": "",
+ "required": false
+ },
"APPSMITH_DISABLE_TELEMETRY": {
"description" : "We want to be transparent and request that you share anonymous usage data with us. This data is purely statistical in nature and helps us understand your needs & provide better support to your self-hosted instance. You can read more about what information is collected in our documentation https://docs.appsmith.com/v/v1.2.1/setup/telemetry",
"value": "false"
diff --git a/app/client/docker/templates/nginx-app.conf.template b/app/client/docker/templates/nginx-app.conf.template
index 4b7c5fdf4e..6b8ed93474 100644
--- a/app/client/docker/templates/nginx-app.conf.template
+++ b/app/client/docker/templates/nginx-app.conf.template
@@ -48,6 +48,7 @@ server {
sub_filter __APPSMITH_MAIL_ENABLED__ '${APPSMITH_MAIL_ENABLED}';
sub_filter __APPSMITH_DISABLE_TELEMETRY__ '${APPSMITH_DISABLE_TELEMETRY}';
sub_filter __APPSMITH_CLOUD_SERVICES_BASE_URL__ '${APPSMITH_CLOUD_SERVICES_BASE_URL}';
+ sub_filter __APPSMITH_RECAPTCHA_SITE_KEY__ '${APPSMITH_RECAPTCHA_SITE_KEY}';
}
location /f {
diff --git a/app/client/netlify.toml b/app/client/netlify.toml
index 3bb6abd265..9c900dc92d 100644
--- a/app/client/netlify.toml
+++ b/app/client/netlify.toml
@@ -8,6 +8,7 @@
REACT_APP_ALGOLIA_SEARCH_INDEX_NAME = "test_appsmith"
REACT_APP_CLIENT_LOG_LEVEL = "debug"
REACT_APP_GOOGLE_MAPS_API_KEY = "AIzaSyBOQFulljufGt3VDhBAwNjZN09KEFufVyg"
+ REACT_APP_GOOGLE_RECAPTCHA_SITE_KEY = ""
REACT_APP_TNC_PP = "true"
REACT_APP_CLOUD_HOSTING = "true"
REACT_APP_INTERCOM_APP_ID = "y10e7138"
diff --git a/app/client/public/index.html b/app/client/public/index.html
index 8079bbba08..df6675bb58 100755
--- a/app/client/public/index.html
+++ b/app/client/public/index.html
@@ -204,7 +204,8 @@
intercomAppID: APP_ID,
mailEnabled: parseConfig("__APPSMITH_MAIL_ENABLED__"),
disableTelemetry: DISABLE_TELEMETRY === "" || DISABLE_TELEMETRY,
- cloudServicesBaseUrl: parseConfig("__APPSMITH_CLOUD_SERVICES_BASE_URL__") || "https://cs.appsmith.com"
+ cloudServicesBaseUrl: parseConfig("__APPSMITH_CLOUD_SERVICES_BASE_URL__") || "https://cs.appsmith.com",
+ googleRecaptchaSiteKey: parseConfig("__APPSMITH_RECAPTCHA_SITE_KEY__"),
};
diff --git a/app/client/src/configs/index.ts b/app/client/src/configs/index.ts
index e4b2b60f9a..a50565f606 100644
--- a/app/client/src/configs/index.ts
+++ b/app/client/src/configs/index.ts
@@ -42,6 +42,7 @@ export type INJECTED_CONFIGS = {
mailEnabled: boolean;
disableTelemetry: boolean;
cloudServicesBaseUrl: string;
+ googleRecaptchaSiteKey: string;
onboardingFormEnabled: boolean;
};
declare global {
@@ -116,6 +117,8 @@ const getConfigsFromEnvVars = (): INJECTED_CONFIGS => {
: false,
disableTelemetry: true,
cloudServicesBaseUrl: process.env.REACT_APP_CLOUD_SERVICES_BASE_URL || "",
+ googleRecaptchaSiteKey:
+ process.env.REACT_APP_GOOGLE_RECAPTCHA_SITE_KEY || "",
onboardingFormEnabled: !!process.env.REACT_APP_SHOW_ONBOARDING_FORM,
};
};
@@ -167,6 +170,11 @@ export const getAppsmithConfigs = (): AppsmithUIConfigs => {
);
const google = getConfig(ENV_CONFIG.google, APPSMITH_FEATURE_CONFIGS.google);
+ const googleRecaptchaSiteKey = getConfig(
+ ENV_CONFIG.googleRecaptchaSiteKey,
+ APPSMITH_FEATURE_CONFIGS.googleRecaptchaSiteKey,
+ );
+
// As the following shows, the config variables can be set using a combination
// of env variables and injected configs
const smartLook = getConfig(
@@ -245,6 +253,10 @@ export const getAppsmithConfigs = (): AppsmithUIConfigs => {
enabled: google.enabled,
apiKey: google.value,
},
+ googleRecaptchaSiteKey: {
+ enabled: googleRecaptchaSiteKey.enabled,
+ apiKey: googleRecaptchaSiteKey.value,
+ },
enableRapidAPI:
ENV_CONFIG.enableRapidAPI || APPSMITH_FEATURE_CONFIGS.enableRapidAPI,
enableGithubOAuth:
diff --git a/app/client/src/configs/types.ts b/app/client/src/configs/types.ts
index fde3769c7c..41fde2417f 100644
--- a/app/client/src/configs/types.ts
+++ b/app/client/src/configs/types.ts
@@ -73,5 +73,9 @@ export type AppsmithUIConfigs = {
cloudServicesBaseUrl: string;
+ googleRecaptchaSiteKey: {
+ enabled: boolean;
+ apiKey: string;
+ };
onboardingFormEnabled: boolean;
};
diff --git a/app/client/src/pages/UserAuth/SignUp.tsx b/app/client/src/pages/UserAuth/SignUp.tsx
index 97604e2671..74c74ebcbc 100644
--- a/app/client/src/pages/UserAuth/SignUp.tsx
+++ b/app/client/src/pages/UserAuth/SignUp.tsx
@@ -35,7 +35,6 @@ import { isEmail, isStrongPassword, isEmptyString } from "utils/formhelpers";
import { SignupFormValues } from "./helpers";
import AnalyticsUtil from "utils/AnalyticsUtil";
-import { getAppsmithConfigs } from "configs";
import { SIGNUP_SUBMIT_PATH } from "constants/ApiConstants";
import { connect } from "react-redux";
import { AppState } from "reducers";
@@ -45,6 +44,8 @@ import PerformanceTracker, {
import { useIntiateOnboarding } from "components/editorComponents/Onboarding/utils";
import { SIGNUP_FORM_EMAIL_FIELD_NAME } from "constants/forms";
+import { getAppsmithConfigs } from "configs";
+import { useScript, ScriptStatus, AddScriptTo } from "utils/hooks/useScript";
const { enableGithubOAuth, enableGoogleOAuth } = getAppsmithConfigs();
const SocialLoginList: string[] = [];
@@ -54,6 +55,13 @@ if (enableGithubOAuth) SocialLoginList.push(SocialLoginTypes.GITHUB);
import { withTheme } from "styled-components";
import { Theme } from "constants/DefaultTheme";
+declare global {
+ interface Window {
+ grecaptcha: any;
+ }
+}
+const { googleRecaptchaSiteKey } = getAppsmithConfigs();
+
const validate = (values: SignupFormValues) => {
const errors: SignupFormValues = {};
if (!values.password || isEmptyString(values.password)) {
@@ -82,6 +90,11 @@ export function SignUp(props: SignUpFormProps) {
const location = useLocation();
const initiateOnboarding = useIntiateOnboarding();
+ const recaptchaStatus = useScript(
+ `https://www.google.com/recaptcha/api.js?render=${googleRecaptchaSiteKey.apiKey}`,
+ AddScriptTo.HEAD,
+ );
+
let showError = false;
let errorMessage = "";
const queryParams = new URLSearchParams(location.search);
@@ -118,7 +131,37 @@ export function SignUp(props: SignUpFormProps) {
{SocialLoginList.length > 0 && (
)}
-
+ {
+ e.preventDefault();
+ const formElement: HTMLFormElement = document.getElementById(
+ "signup-form",
+ ) as HTMLFormElement;
+ if (
+ googleRecaptchaSiteKey.enabled &&
+ recaptchaStatus === ScriptStatus.READY
+ ) {
+ window.grecaptcha
+ .execute(googleRecaptchaSiteKey.apiKey, {
+ action: "submit",
+ })
+ .then(function(token: any) {
+ formElement &&
+ formElement.setAttribute(
+ "action",
+ `${signupURL}?recaptchaToken=${token}`,
+ );
+ formElement && formElement.submit();
+ });
+ } else {
+ formElement && formElement.submit();
+ }
+ return false;
+ }}
+ >
/etc/nginx/conf.d/default.conf.template.1
envsubst "\$PORT" < /etc/nginx/conf.d/default.conf.template.1 > /etc/nginx/conf.d/default.conf
diff --git a/deploy/heroku/default.conf.template b/deploy/heroku/default.conf.template
index 8362ccc505..490cacb32d 100644
--- a/deploy/heroku/default.conf.template
+++ b/deploy/heroku/default.conf.template
@@ -32,6 +32,9 @@ server {
sub_filter __APPSMITH_INTERCOM_APP_ID__ '${APPSMITH_INTERCOM_APP_ID}';
sub_filter __APPSMITH_MAIL_ENABLED__ '${APPSMITH_MAIL_ENABLED}';
sub_filter __APPSMITH_DISABLE_TELEMETRY__ '${APPSMITH_DISABLE_TELEMETRY}';
+ sub_filter __APPSMITH_RECAPTCHA_SITE_KEY__ '${APPSMITH_RECAPTCHA_SITE_KEY}';
+ sub_filter __APPSMITH_RECAPTCHA_SECRET_KEY__ '${APPSMITH_RECAPTCHA_SECRET_KEY}';
+ sub_filter __APPSMITH_RECAPTCHA_ENABLED__ '${APPSMITH_RECAPTCHA_ENABLED}';
}
location /f {
diff --git a/deploy/k8s/scripts/appsmith-configmap.yaml.sh b/deploy/k8s/scripts/appsmith-configmap.yaml.sh
index d664292f6f..bf7b314546 100644
--- a/deploy/k8s/scripts/appsmith-configmap.yaml.sh
+++ b/deploy/k8s/scripts/appsmith-configmap.yaml.sh
@@ -30,4 +30,7 @@ data:
APPSMITH_REDIS_URL: redis://redis-service:6379
APPSMITH_MONGODB_URI: $mongo_protocol$encoded_mongo_root_user:$encoded_mongo_root_password@$mongo_host/$mongo_db?retryWrites=true&authSource=admin
APPSMITH_DISABLE_TELEMETRY: "$disable_telemetry"
+ APPSMITH_RECAPTCHA_SITE_KEY= ""
+ APPSMITH_RECAPTCHA_SECRET_KEY= ""
+ APPSMITH_RECAPTCHA_ENABLED= "false"
EOF
diff --git a/deploy/k8s/scripts/nginx-configmap.yaml b/deploy/k8s/scripts/nginx-configmap.yaml
index b9253d36bf..eef8665258 100644
--- a/deploy/k8s/scripts/nginx-configmap.yaml
+++ b/deploy/k8s/scripts/nginx-configmap.yaml
@@ -37,6 +37,9 @@ data:
sub_filter __APPSMITH_MAIL_ENABLED__ '${APPSMITH_MAIL_ENABLED}';
sub_filter __APPSMITH_DISABLE_TELEMETRY__ '${APPSMITH_DISABLE_TELEMETRY}';
sub_filter __APPSMITH_CLOUD_SERVICES_BASE_URL__ '${APPSMITH_CLOUD_SERVICES_BASE_URL}';
+ sub_filter __APPSMITH_RECAPTCHA_SITE_KEY__ '${APPSMITH_RECAPTCHA_SITE_KEY}';
+ sub_filter __APPSMITH_RECAPTCHA_SECRET_KEY__ '${APPSMITH_RECAPTCHA_SECRET_KEY}';
+ sub_filter __APPSMITH_RECAPTCHA_ENABLED__ '${APPSMITH_RECAPTCHA_ENABLED}';
}
location /f {
diff --git a/deploy/template/docker.env.sh b/deploy/template/docker.env.sh
index 6bbeb5e901..d1561b8902 100644
--- a/deploy/template/docker.env.sh
+++ b/deploy/template/docker.env.sh
@@ -59,4 +59,10 @@ APPSMITH_DISABLE_TELEMETRY=$disable_telemetry
# APPSMITH_CODEC_SIZE=
# *******************************
+# ***** Google Recaptcha Config ******
+# APPSMITH_RECAPTCHA_SITE_KEY=
+# APPSMITH_RECAPTCHA_SECRET_KEY=
+# APPSMITH_RECAPTCHA_ENABLED=
+# ************************************
+
EOF
diff --git a/deploy/template/nginx_app.conf.sh b/deploy/template/nginx_app.conf.sh
index cb0a0928b4..8954753b82 100644
--- a/deploy/template/nginx_app.conf.sh
+++ b/deploy/template/nginx_app.conf.sh
@@ -49,6 +49,9 @@ $NGINX_SSL_CMNT server_name $custom_domain ;
sub_filter __APPSMITH_INTERCOM_APP_ID__ '\${APPSMITH_INTERCOM_APP_ID}';
sub_filter __APPSMITH_MAIL_ENABLED__ '\${APPSMITH_MAIL_ENABLED}';
sub_filter __APPSMITH_DISABLE_TELEMETRY__ '\${APPSMITH_DISABLE_TELEMETRY}';
+ sub_filter __APPSMITH_RECAPTCHA_SITE_KEY__ '\${APPSMITH_RECAPTCHA_SITE_KEY}';
+ sub_filter __APPSMITH_RECAPTCHA_SECRET_KEY__ '\${APPSMITH_RECAPTCHA_SECRET_KEY}';
+ sub_filter __APPSMITH_RECAPTCHA_ENABLED__ '\${APPSMITH_RECAPTCHA_ENABLED}';
}
location /f {
@@ -106,6 +109,9 @@ $NGINX_SSL_CMNT sub_filter __APPSMITH_VERSION_RELEASE_DATE__ '\${APPSMITH
$NGINX_SSL_CMNT sub_filter __APPSMITH_INTERCOM_APP_ID__ '\${APPSMITH_INTERCOM_APP_ID}';
$NGINX_SSL_CMNT sub_filter __APPSMITH_MAIL_ENABLED__ '\${APPSMITH_MAIL_ENABLED}';
$NGINX_SSL_CMNT sub_filter __APPSMITH_DISABLE_TELEMETRY__ '\${APPSMITH_DISABLE_TELEMETRY}';
+$NGINX_SSL_CMNT sub_filter __APPSMITH_RECAPTCHA_SITE_KEY__ '\${APPSMITH_RECAPTCHA_SITE_KEY};
+$NGINX_SSL_CMNT sub_filter __APPSMITH_RECAPTCHA_SECRET_KEY__ '\${APPSMITH_RECAPTCHA_SECRET_KEY};
+$NGINX_SSL_CMNT sub_filter __APPSMITH_RECAPTCHA_ENABLED__ '\${APPSMITH_RECAPTCHA_ENABLED}';
$NGINX_SSL_CMNT }
$NGINX_SSL_CMNT
$NGINX_SSL_CMNT location /f {