chore: Move signup_disabled and form_login_enabled from envs to DB (#39882)

## Description
> [!TIP]  
> _Add a TL;DR when the description is longer than 500 words or
extremely technical (helps the content, marketing, and DevRel team)._
>
> _Please also include relevant motivation and context. List any
dependencies that are required for this change. Add links to Notion,
Figma or any other documents that might be relevant to the PR._


/test Settings

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/14058953075>
> Commit: 80445acc542f201c01a40a09323097a946959e50
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=14058953075&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.Settings`
> Spec:
> <hr>Tue, 25 Mar 2025 12:19:59 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [ ] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Organizations now control form login and signup behavior with updated,
clearer configuration flags.
- **Refactor**
- Renamed settings to reflect an enabled state for form login and a
disabled state for signup.
- Removed deprecated restart functionality and reorganized utility
classes for improved maintainability.
- **Chores/Tests**
- Updated tests and environment examples to align with the new
configuration settings and ensure consistent behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Abhijeet 2025-03-26 11:26:00 +05:30 committed by GitHub
parent 93fdfc967d
commit 73e239b9f8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 260 additions and 143 deletions

View File

@ -83,8 +83,8 @@ describe("Form Login test functionality", function () {
cy.get(adminSettings.formloginButton).click(); cy.get(adminSettings.formloginButton).click();
cy.wait(2000); cy.wait(2000);
// disable form signup // disable form signup
cy.get(adminSettings.formLoginDisabled).should("have.value", "on"); cy.get(adminSettings.formLoginEnabled).should("have.value", "on");
cy.get(adminSettings.formLoginDisabled).click({ force: true }); cy.get(adminSettings.formLoginEnabled).click({ force: true });
cy.wait(2000); cy.wait(2000);
// assert server is restarting // assert server is restarting
cy.get(adminSettings.saveButton).should("be.visible"); cy.get(adminSettings.saveButton).should("be.visible");
@ -109,7 +109,7 @@ describe("Form Login test functionality", function () {
.should("be.visible") .should("be.visible")
.should("contain", "Enable"); .should("contain", "Enable");
cy.get(adminSettings.formloginButton).click(); cy.get(adminSettings.formloginButton).click();
cy.get(adminSettings.formLoginDisabled).click({ force: true }); cy.get(adminSettings.formLoginEnabled).click({ force: true });
cy.wait(2000); cy.wait(2000);
// assert server is restarting // assert server is restarting
cy.get(adminSettings.saveButton).should("be.visible"); cy.get(adminSettings.saveButton).should("be.visible");

View File

@ -24,8 +24,8 @@ export default {
loginWithGoogle: "[data-testid='login-with-Google']", loginWithGoogle: "[data-testid='login-with-Google']",
loginWithGithub: "[data-testid='login-with-Github']", loginWithGithub: "[data-testid='login-with-Github']",
disconnectBtn: "[data-testid='disconnect-service-button']", disconnectBtn: "[data-testid='disconnect-service-button']",
formSignupDisabled: "[data-testid='APPSMITH_SIGNUP_DISABLED']", formSignupDisabled: "[data-testid='isSignupDisabled']",
formLoginDisabled: "[data-testid='APPSMITH_FORM_LOGIN_DISABLED']", formLoginEnabled: "[data-testid='isFormLoginEnabled']",
embedSettings: ".t--admin-settings-APPSMITH_ALLOWED_FRAME_ANCESTORS", embedSettings: ".t--admin-settings-APPSMITH_ALLOWED_FRAME_ANCESTORS",
upgrade: "[data-testid='t--button-upgrade']", upgrade: "[data-testid='t--button-upgrade']",
accessControl: ".t--settings-category-access-control", accessControl: ".t--settings-category-access-control",

View File

@ -7,6 +7,8 @@ export const organizationConfigConnection: string[] = [
"hideWatermark", "hideWatermark",
"userSessionTimeoutInMinutes", "userSessionTimeoutInMinutes",
"isAtomicPushAllowed", "isAtomicPushAllowed",
"isFormLoginEnabled",
"isSignupDisabled",
]; ];
export const RESTART_POLL_TIMEOUT = 2 * 150 * 1000; export const RESTART_POLL_TIMEOUT = 2 * 150 * 1000;

View File

@ -48,13 +48,13 @@ const FormAuth: AdminConfigType = {
canSave: true, canSave: true,
settings: [ settings: [
{ {
id: "APPSMITH_FORM_LOGIN_DISABLED", id: "isFormLoginEnabled",
category: SettingCategories.FORM_AUTH, category: SettingCategories.FORM_AUTH,
controlType: SettingTypes.TOGGLE, controlType: SettingTypes.TOGGLE,
label: "form login", label: "form login",
}, },
{ {
id: "APPSMITH_SIGNUP_DISABLED", id: "isSignupDisabled",
category: SettingCategories.FORM_AUTH, category: SettingCategories.FORM_AUTH,
controlType: SettingTypes.TOGGLE, controlType: SettingTypes.TOGGLE,
label: "Form signup", label: "Form signup",

View File

@ -69,6 +69,10 @@ export function* updateOrganizationConfigSaga(
"emailVerificationEnabled", "emailVerificationEnabled",
); );
const hasFormLoginSetting = settings.hasOwnProperty("isFormLoginEnabled");
const hasSignupDisabledSetting =
settings.hasOwnProperty("isSignupDisabled");
const response: ApiResponse = yield call( const response: ApiResponse = yield call(
OrganizationApi.updateOrganizationConfig, OrganizationApi.updateOrganizationConfig,
action.payload, action.payload,
@ -94,6 +98,18 @@ export function* updateOrganizationConfigSaga(
}); });
} }
if (hasFormLoginSetting) {
AnalyticsUtil.logEvent("GENERAL_SETTINGS_UPDATE", {
enabled: settings["isFormLoginEnabled"],
});
}
if (hasSignupDisabledSetting) {
AnalyticsUtil.logEvent("GENERAL_SETTINGS_UPDATE", {
enabled: settings["isSignupDisabled"],
});
}
if (hasEmailVerificationSetting) { if (hasEmailVerificationSetting) {
AnalyticsUtil.logEvent("EMAIL_VERIFICATION_SETTING_UPDATE", { AnalyticsUtil.logEvent("EMAIL_VERIFICATION_SETTING_UPDATE", {
enabled: settings["emailVerificationEnabled"], enabled: settings["emailVerificationEnabled"],

View File

@ -48,6 +48,9 @@ export const getThirdPartyAuths = (state: AppState): string[] =>
export const getIsFormLoginEnabled = (state: AppState): boolean => export const getIsFormLoginEnabled = (state: AppState): boolean =>
state.organization?.organizationConfiguration?.isFormLoginEnabled ?? true; state.organization?.organizationConfiguration?.isFormLoginEnabled ?? true;
export const getIsSignupDisabled = (state: AppState): boolean =>
state.organization?.organizationConfiguration?.isSignupDisabled ?? false;
export const getInstanceId = (state: AppState): string => export const getInstanceId = (state: AppState): string =>
state.organization?.instanceId; state.organization?.instanceId;

View File

@ -18,8 +18,7 @@ export const saveAllowed = (
socialLoginList.length + (isFormLoginEnabled ? 1 : 0); socialLoginList.length + (isFormLoginEnabled ? 1 : 0);
if (connectedMethodsCount === 1) { if (connectedMethodsCount === 1) {
const checkFormLogin = const checkFormLogin = isFormLoginEnabled,
!("APPSMITH_FORM_LOGIN_DISABLED" in settings) && isFormLoginEnabled,
checkGoogleAuth = checkGoogleAuth =
settings["APPSMITH_OAUTH2_GOOGLE_CLIENT_ID"] !== "" && settings["APPSMITH_OAUTH2_GOOGLE_CLIENT_ID"] !== "" &&
socialLoginList.includes("google"), socialLoginList.includes("google"),

View File

@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useMemo } from "react"; import React, { useCallback, useEffect, useMemo, useState } from "react";
import { saveSettings } from "ee/actions/settingsAction"; import { saveSettings } from "ee/actions/settingsAction";
import { SETTINGS_FORM_NAME } from "ee/constants/forms"; import { SETTINGS_FORM_NAME } from "ee/constants/forms";
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
@ -89,6 +89,8 @@ export function SettingsForm(
); );
const isFormLoginEnabled = useSelector(getIsFormLoginEnabled); const isFormLoginEnabled = useSelector(getIsFormLoginEnabled);
const socialLoginList = useSelector(getThirdPartyAuths); const socialLoginList = useSelector(getThirdPartyAuths);
const [initialFormLoginEnabled, setInitialFormLoginEnabled] =
useState(isFormLoginEnabled);
const updatedOrganizationSettings = useMemo( const updatedOrganizationSettings = useMemo(
() => Object.keys(props.settings).filter((s) => isOrganizationConfig(s)), () => Object.keys(props.settings).filter((s) => isOrganizationConfig(s)),
@ -103,6 +105,11 @@ export function SettingsForm(
!isOrganizationConfig(s.id), !isOrganizationConfig(s.id),
); );
// Store the initial value of isFormLoginEnabled on component mount
useEffect(() => {
setInitialFormLoginEnabled(isFormLoginEnabled);
}, [category, subCategory]);
const saveChangedSettings = () => { const saveChangedSettings = () => {
const settingsKeyLength = Object.keys(props.settings).length; const settingsKeyLength = Object.keys(props.settings).length;
const isOnlyEnvSettings = const isOnlyEnvSettings =
@ -151,7 +158,23 @@ export function SettingsForm(
const onSave = () => { const onSave = () => {
if (checkMandatoryFileds()) { if (checkMandatoryFileds()) {
if (saveAllowed(props.settings, isFormLoginEnabled, socialLoginList)) { // Use initialFormLoginEnabled instead of the current state value for the check
let effectiveFormLoginEnabled = initialFormLoginEnabled;
// Check if isFormLoginEnabled is being updated in the current form
if (props.settings["isFormLoginEnabled"] !== undefined) {
// Convert to boolean if it's a string, otherwise use as is since we expect a boolean
const settingValue = props.settings["isFormLoginEnabled"];
effectiveFormLoginEnabled =
typeof settingValue === "string"
? settingValue === "true"
: Boolean(settingValue);
}
if (
saveAllowed(props.settings, effectiveFormLoginEnabled, socialLoginList)
) {
AnalyticsUtil.logEvent("ADMIN_SETTINGS_SAVE", { AnalyticsUtil.logEvent("ADMIN_SETTINGS_SAVE", {
method: pageTitle, method: pageTitle,
}); });
@ -224,6 +247,13 @@ export function SettingsForm(
useEffect(onClear, [subCategory]); useEffect(onClear, [subCategory]);
useEffect(() => {
// Reset the initialFormLoginEnabled value when navigating to a different category
return () => {
setInitialFormLoginEnabled(isFormLoginEnabled);
};
}, [category, subCategory]);
const onReleaseNotesClose = useCallback(() => { const onReleaseNotesClose = useCallback(() => {
dispatch({ dispatch({
type: ReduxActionTypes.TOGGLE_RELEASE_NOTES, type: ReduxActionTypes.TOGGLE_RELEASE_NOTES,
@ -244,8 +274,9 @@ export function SettingsForm(
// TODO: Fix this the next time the file is edited // TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const updatedSettings: any = {}; const updatedSettings: any = {};
// Use the initial value to determine if there are enough login methods
const connectedMethodsCount = const connectedMethodsCount =
socialLoginList.length + (isFormLoginEnabled ? 1 : 0); socialLoginList.length + (initialFormLoginEnabled ? 1 : 0);
if (connectedMethodsCount >= 2) { if (connectedMethodsCount >= 2) {
_.forEach(currentSettings, (setting: Setting) => { _.forEach(currentSettings, (setting: Setting) => {

View File

@ -1,9 +1,9 @@
package com.appsmith.server.authentication.handlers; package com.appsmith.server.authentication.handlers;
import com.appsmith.server.authentication.handlers.ce.AuthenticationSuccessHandlerCE; import com.appsmith.server.authentication.handlers.ce.AuthenticationSuccessHandlerCE;
import com.appsmith.server.helpers.InstanceVariablesHelper;
import com.appsmith.server.helpers.RedirectHelper; import com.appsmith.server.helpers.RedirectHelper;
import com.appsmith.server.helpers.WorkspaceServiceHelper; import com.appsmith.server.helpers.WorkspaceServiceHelper;
import com.appsmith.server.instanceconfigs.helpers.InstanceVariablesHelper;
import com.appsmith.server.ratelimiting.RateLimitService; import com.appsmith.server.ratelimiting.RateLimitService;
import com.appsmith.server.repositories.UserRepository; import com.appsmith.server.repositories.UserRepository;
import com.appsmith.server.repositories.WorkspaceRepository; import com.appsmith.server.repositories.WorkspaceRepository;

View File

@ -10,9 +10,9 @@ import com.appsmith.server.domains.LoginSource;
import com.appsmith.server.domains.User; import com.appsmith.server.domains.User;
import com.appsmith.server.domains.Workspace; import com.appsmith.server.domains.Workspace;
import com.appsmith.server.dtos.ResendEmailVerificationDTO; import com.appsmith.server.dtos.ResendEmailVerificationDTO;
import com.appsmith.server.helpers.InstanceVariablesHelper;
import com.appsmith.server.helpers.RedirectHelper; import com.appsmith.server.helpers.RedirectHelper;
import com.appsmith.server.helpers.WorkspaceServiceHelper; import com.appsmith.server.helpers.WorkspaceServiceHelper;
import com.appsmith.server.instanceconfigs.helpers.InstanceVariablesHelper;
import com.appsmith.server.ratelimiting.RateLimitService; import com.appsmith.server.ratelimiting.RateLimitService;
import com.appsmith.server.repositories.UserRepository; import com.appsmith.server.repositories.UserRepository;
import com.appsmith.server.repositories.WorkspaceRepository; import com.appsmith.server.repositories.WorkspaceRepository;
@ -103,13 +103,13 @@ public class AuthenticationSuccessHandlerCE implements ServerAuthenticationSucce
return Mono.just(FALSE); return Mono.just(FALSE);
} else { } else {
return emailVerificationEnabledMono.flatMap(emailVerificationEnabled -> { return emailVerificationEnabledMono.flatMap(emailVerificationEnabled -> {
// email verification not enabled at the org // email verification not enabled
if (!TRUE.equals(emailVerificationEnabled)) { if (!TRUE.equals(emailVerificationEnabled)) {
user.setEmailVerificationRequired(FALSE); user.setEmailVerificationRequired(FALSE);
return userRepository.save(user).then(Mono.just(FALSE)); return userRepository.save(user).then(Mono.just(FALSE));
} else { } else {
// scenario when at the time of signup, the email verification was disabled at the org // scenario when at the time of signup, the email verification was disabled but later on
// but later on turned on, now when this user logs in, it will not be prompted to verify // turned on, now when this user logs in, it will not be prompted to verify
// as the configuration at time of signup is considered for any user. // as the configuration at time of signup is considered for any user.
// for old users, the login works as expected, without the need to verify // for old users, the login works as expected, without the need to verify
if (!TRUE.equals(user.getEmailVerificationRequired())) { if (!TRUE.equals(user.getEmailVerificationRequired())) {

View File

@ -36,9 +36,6 @@ public class CommonConfig {
public static final Integer LATEST_INSTANCE_SCHEMA_VERSION = 2; public static final Integer LATEST_INSTANCE_SCHEMA_VERSION = 2;
@Setter(AccessLevel.NONE)
private boolean isSignupDisabled = false;
@Setter(AccessLevel.NONE) @Setter(AccessLevel.NONE)
private Set<String> adminEmails = Collections.emptySet(); private Set<String> adminEmails = Collections.emptySet();
@ -129,12 +126,6 @@ public class CommonConfig {
adminEmails = Set.of(value.trim().split("\\s*,\\s*")); adminEmails = Set.of(value.trim().split("\\s*,\\s*"));
} }
@Autowired
public void setSignupDisabled(@Value("${signup.disabled}") String value) {
// If `true`, then disable signup. If anything else, including empty string, then signups will be enabled.
isSignupDisabled = "true".equalsIgnoreCase(value);
}
public Long getCurrentTimeInstantEpochMilli() { public Long getCurrentTimeInstantEpochMilli() {
return Instant.now().toEpochMilli(); return Instant.now().toEpochMilli();
} }

View File

@ -13,7 +13,6 @@ public enum EnvVariables {
APPSMITH_MAIL_USERNAME, APPSMITH_MAIL_USERNAME,
APPSMITH_MAIL_PASSWORD, APPSMITH_MAIL_PASSWORD,
APPSMITH_MAIL_SMTP_TLS_ENABLED, APPSMITH_MAIL_SMTP_TLS_ENABLED,
APPSMITH_SIGNUP_DISABLED,
APPSMITH_SIGNUP_ALLOWED_DOMAINS, APPSMITH_SIGNUP_ALLOWED_DOMAINS,
APPSMITH_ADMIN_EMAILS, APPSMITH_ADMIN_EMAILS,
APPSMITH_RECAPTCHA_SITE_KEY, APPSMITH_RECAPTCHA_SITE_KEY,
@ -24,7 +23,6 @@ public enum EnvVariables {
APPSMITH_OAUTH2_GITHUB_CLIENT_ID, APPSMITH_OAUTH2_GITHUB_CLIENT_ID,
APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET, APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET,
APPSMITH_CUSTOM_DOMAIN, APPSMITH_CUSTOM_DOMAIN,
APPSMITH_FORM_LOGIN_DISABLED,
APPSMITH_ALLOWED_FRAME_ANCESTORS, APPSMITH_ALLOWED_FRAME_ANCESTORS,
APPSMITH_DISABLE_IFRAME_WIDGET_SANDBOX, APPSMITH_DISABLE_IFRAME_WIDGET_SANDBOX,
APPSMITH_NEW_RELIC_ACCOUNT_ENABLE, APPSMITH_NEW_RELIC_ACCOUNT_ENABLE,

View File

@ -12,8 +12,6 @@ import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable; import java.io.Serializable;
import static com.appsmith.external.helpers.StringUtils.dotted;
@Getter @Getter
@Setter @Setter
@ToString @ToString
@ -38,8 +36,5 @@ public class Organization extends BaseDomain implements Serializable {
// TODO add SSO and other configurations here after migrating from environment variables to database configuration // TODO add SSO and other configurations here after migrating from environment variables to database configuration
public static class Fields extends BaseDomain.Fields { public static class Fields extends BaseDomain.Fields {}
public static final String organizationConfiguration_isRestartRequired =
dotted(organizationConfiguration, OrganizationConfiguration.Fields.isRestartRequired);
}
} }

View File

@ -27,6 +27,8 @@ public class OrganizationConfigurationCE implements Serializable {
private Boolean isFormLoginEnabled; private Boolean isFormLoginEnabled;
private Boolean isSignupDisabled;
@Transient @Transient
@Deprecated(forRemoval = true, since = "v1.65") @Deprecated(forRemoval = true, since = "v1.65")
private String instanceName; private String instanceName;
@ -58,10 +60,6 @@ public class OrganizationConfigurationCE implements Serializable {
// 2. Because of grandfathering via cron where organization level feature flags are fetched // 2. Because of grandfathering via cron where organization level feature flags are fetched
Map<FeatureFlagEnum, FeatureMigrationType> featuresWithPendingMigration; Map<FeatureFlagEnum, FeatureMigrationType> featuresWithPendingMigration;
// This variable is used to indicate if the server needs to be restarted after the migration based on feature flags
// is complete.
Boolean isRestartRequired;
Boolean isStrongPasswordPolicyEnabled; Boolean isStrongPasswordPolicyEnabled;
private Boolean isAtomicPushAllowed = false; private Boolean isAtomicPushAllowed = false;
@ -84,6 +82,7 @@ public class OrganizationConfigurationCE implements Serializable {
googleMapsKey = ObjectUtils.defaultIfNull(organizationConfiguration.getGoogleMapsKey(), googleMapsKey); googleMapsKey = ObjectUtils.defaultIfNull(organizationConfiguration.getGoogleMapsKey(), googleMapsKey);
isFormLoginEnabled = isFormLoginEnabled =
ObjectUtils.defaultIfNull(organizationConfiguration.getIsFormLoginEnabled(), isFormLoginEnabled); ObjectUtils.defaultIfNull(organizationConfiguration.getIsFormLoginEnabled(), isFormLoginEnabled);
isSignupDisabled = ObjectUtils.defaultIfNull(organizationConfiguration.getIsSignupDisabled(), isSignupDisabled);
instanceName = ObjectUtils.defaultIfNull(organizationConfiguration.getInstanceName(), instanceName); instanceName = ObjectUtils.defaultIfNull(organizationConfiguration.getInstanceName(), instanceName);
emailVerificationEnabled = ObjectUtils.defaultIfNull( emailVerificationEnabled = ObjectUtils.defaultIfNull(
organizationConfiguration.getEmailVerificationEnabled(), emailVerificationEnabled); organizationConfiguration.getEmailVerificationEnabled(), emailVerificationEnabled);

View File

@ -912,9 +912,9 @@ public enum AppsmithError {
ErrorType.INTERNAL_ERROR, ErrorType.INTERNAL_ERROR,
null), null),
ORGANIZATION_EMAIL_VERIFICATION_NOT_ENABLED( EMAIL_VERIFICATION_NOT_ENABLED(
400, 400,
AppsmithErrorCode.ORGANIZATION_EMAIL_VERIFICATION_NOT_ENABLED.getCode(), AppsmithErrorCode.EMAIL_VERIFICATION_NOT_ENABLED.getCode(),
"Email verification is not enabled. Please contact your admin", "Email verification is not enabled. Please contact your admin",
AppsmithErrorAction.DEFAULT, AppsmithErrorAction.DEFAULT,
"Email verification not enabled", "Email verification not enabled",

View File

@ -123,7 +123,7 @@ public enum AppsmithErrorCode {
USER_EMAIL_ALREADY_VERIFIED("AE-EMV-4095", "User email already verified"), USER_EMAIL_ALREADY_VERIFIED("AE-EMV-4095", "User email already verified"),
EMAIL_VERIFICATION_TOKEN_EXPIRED("AE-EMV-4096", "Email Verification Token expired"), EMAIL_VERIFICATION_TOKEN_EXPIRED("AE-EMV-4096", "Email Verification Token expired"),
ORGANIZATION_EMAIL_VERIFICATION_NOT_ENABLED("AE-EMV-4097", "Email Verification not enabled"), EMAIL_VERIFICATION_NOT_ENABLED("AE-EMV-4097", "Email Verification not enabled"),
INVALID_EMAIL_VERIFICATION("AE-EMV-4098", "Invalid email verification request"), INVALID_EMAIL_VERIFICATION("AE-EMV-4098", "Invalid email verification request"),

View File

@ -0,0 +1,3 @@
package com.appsmith.server.instanceconfigs.constants;
public interface AllowedInstanceVariables extends AllowedInstanceVariablesCE {}

View File

@ -0,0 +1,7 @@
package com.appsmith.server.instanceconfigs.constants;
public interface AllowedInstanceVariablesCE {
String INSTANCE_NAME = "instanceName";
String EMAIL_VERIFICATION_ENABLED = "emailVerificationEnabled";
String GOOGLE_MAPS_KEY = "googleMapsKey";
}

View File

@ -1,17 +1,12 @@
package com.appsmith.server.helpers; package com.appsmith.server.instanceconfigs.helpers;
import com.appsmith.server.helpers.ce.InstanceVariablesHelperCE;
import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.ConfigService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/**
* Helper class for accessing instance variables from the instance config
*/
@Component @Component
@Slf4j @Slf4j
public class InstanceVariablesHelper extends InstanceVariablesHelperCE { public class InstanceVariablesHelper extends InstanceVariablesHelperCE {
public InstanceVariablesHelper(ConfigService configService) { public InstanceVariablesHelper(ConfigService configService) {
super(configService); super(configService);
} }

View File

@ -1,4 +1,4 @@
package com.appsmith.server.helpers.ce; package com.appsmith.server.instanceconfigs.helpers;
import com.appsmith.server.constants.Appsmith; import com.appsmith.server.constants.Appsmith;
import com.appsmith.server.domains.OrganizationConfiguration; import com.appsmith.server.domains.OrganizationConfiguration;
@ -10,6 +10,10 @@ import reactor.core.publisher.Mono;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static com.appsmith.server.instanceconfigs.constants.AllowedInstanceVariables.EMAIL_VERIFICATION_ENABLED;
import static com.appsmith.server.instanceconfigs.constants.AllowedInstanceVariables.GOOGLE_MAPS_KEY;
import static com.appsmith.server.instanceconfigs.constants.AllowedInstanceVariables.INSTANCE_NAME;
/** /**
* Helper class for accessing instance variables from the instance config * Helper class for accessing instance variables from the instance config
*/ */
@ -23,7 +27,7 @@ public class InstanceVariablesHelperCE {
*/ */
public Mono<String> getInstanceName() { public Mono<String> getInstanceName() {
return configService.getInstanceVariables().map(instanceVariables -> { return configService.getInstanceVariables().map(instanceVariables -> {
Object value = instanceVariables.getOrDefault("instanceName", Appsmith.DEFAULT_INSTANCE_NAME); Object value = instanceVariables.getOrDefault(INSTANCE_NAME, Appsmith.DEFAULT_INSTANCE_NAME);
return value != null ? value.toString() : Appsmith.DEFAULT_INSTANCE_NAME; return value != null ? value.toString() : Appsmith.DEFAULT_INSTANCE_NAME;
}); });
} }
@ -34,7 +38,7 @@ public class InstanceVariablesHelperCE {
*/ */
public Mono<Boolean> isEmailVerificationEnabled() { public Mono<Boolean> isEmailVerificationEnabled() {
return configService.getInstanceVariables().map(instanceVariables -> { return configService.getInstanceVariables().map(instanceVariables -> {
Object value = instanceVariables.getOrDefault("emailVerificationEnabled", false); Object value = instanceVariables.getOrDefault(EMAIL_VERIFICATION_ENABLED, false);
if (value instanceof Boolean) { if (value instanceof Boolean) {
return (Boolean) value; return (Boolean) value;
} }
@ -48,24 +52,24 @@ public class InstanceVariablesHelperCE {
*/ */
public Mono<String> getGoogleMapsKey() { public Mono<String> getGoogleMapsKey() {
return configService.getInstanceVariables().map(instanceVariables -> { return configService.getInstanceVariables().map(instanceVariables -> {
Object value = instanceVariables.getOrDefault("googleMapsKey", ""); Object value = instanceVariables.getOrDefault(GOOGLE_MAPS_KEY, "");
return value != null ? value.toString() : ""; return value != null ? value.toString() : "";
}); });
} }
public OrganizationConfiguration populateOrgConfigWithInstanceVariables( public OrganizationConfiguration populateOrgConfigWithInstanceVariables(
Map<String, Object> instanceVariables, OrganizationConfiguration organizationConfiguration) { Map<String, Object> instanceVariables, OrganizationConfiguration organizationConfiguration) {
Object value = instanceVariables.getOrDefault("instanceName", Appsmith.DEFAULT_INSTANCE_NAME); Object value = instanceVariables.getOrDefault(INSTANCE_NAME, Appsmith.DEFAULT_INSTANCE_NAME);
organizationConfiguration.setInstanceName(value != null ? value.toString() : Appsmith.DEFAULT_INSTANCE_NAME); organizationConfiguration.setInstanceName(value != null ? value.toString() : Appsmith.DEFAULT_INSTANCE_NAME);
value = instanceVariables.getOrDefault("emailVerificationEnabled", false); value = instanceVariables.getOrDefault(EMAIL_VERIFICATION_ENABLED, false);
if (value instanceof Boolean) { if (value instanceof Boolean) {
organizationConfiguration.setEmailVerificationEnabled((Boolean) value); organizationConfiguration.setEmailVerificationEnabled((Boolean) value);
} else { } else {
organizationConfiguration.setEmailVerificationEnabled(Boolean.FALSE); organizationConfiguration.setEmailVerificationEnabled(Boolean.FALSE);
} }
value = instanceVariables.getOrDefault("googleMapsKey", ""); value = instanceVariables.getOrDefault(GOOGLE_MAPS_KEY, "");
organizationConfiguration.setGoogleMapsKey(value != null ? value.toString() : ""); organizationConfiguration.setGoogleMapsKey(value != null ? value.toString() : "");
return organizationConfiguration; return organizationConfiguration;
@ -85,13 +89,13 @@ public class InstanceVariablesHelperCE {
protected Map<String, Object> updateAllowedInstanceVariables(OrganizationConfiguration orgConfig) { protected Map<String, Object> updateAllowedInstanceVariables(OrganizationConfiguration orgConfig) {
Map<String, Object> instanceVariables = new HashMap<>(); Map<String, Object> instanceVariables = new HashMap<>();
if (StringUtils.hasLength(orgConfig.getInstanceName())) { if (StringUtils.hasLength(orgConfig.getInstanceName())) {
instanceVariables.put("instanceName", orgConfig.getInstanceName()); instanceVariables.put(INSTANCE_NAME, orgConfig.getInstanceName());
} }
if (orgConfig.getEmailVerificationEnabled() != null) { if (orgConfig.getEmailVerificationEnabled() != null) {
instanceVariables.put("emailVerificationEnabled", orgConfig.getEmailVerificationEnabled()); instanceVariables.put(EMAIL_VERIFICATION_ENABLED, orgConfig.getEmailVerificationEnabled());
} }
if (StringUtils.hasLength(orgConfig.getGoogleMapsKey())) { if (StringUtils.hasLength(orgConfig.getGoogleMapsKey())) {
instanceVariables.put("googleMapsKey", orgConfig.getGoogleMapsKey()); instanceVariables.put(GOOGLE_MAPS_KEY, orgConfig.getGoogleMapsKey());
} }
return instanceVariables; return instanceVariables;
} }

View File

@ -0,0 +1,51 @@
package com.appsmith.server.migrations.db.ce;
import com.appsmith.server.configurations.CommonConfig;
import com.appsmith.server.domains.Organization;
import io.mongock.api.annotations.ChangeUnit;
import io.mongock.api.annotations.Execution;
import io.mongock.api.annotations.RollbackExecution;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import java.io.IOException;
import static com.appsmith.server.migrations.db.ce.Migration021MoveGoogleMapsKeyToTenantConfiguration.commentEnvInFile;
@Slf4j
@RequiredArgsConstructor
@ChangeUnit(order = "071", id = "move-form-login-disabled-to-organization-configuration")
public class Migration071MoveFormLoginDisabledToOrganizationConfiguration {
private final MongoTemplate mongoTemplate;
private final CommonConfig commonConfig;
@RollbackExecution
public void rollbackExecution() {}
@Execution
public void executeMigration() throws IOException {
final String envName = "APPSMITH_FORM_LOGIN_DISABLED";
final String formLoginDisabledValue = System.getenv(envName);
// Default to false if the environment variable is not present or empty
boolean formLoginDisabled = false;
if (StringUtils.isNotEmpty(formLoginDisabledValue)) {
// Convert the string value to a boolean if env is present
formLoginDisabled = Boolean.parseBoolean(formLoginDisabledValue);
// Comment out the environment variable in the .env file
commentEnvInFile(envName, commonConfig.getEnvFilePath());
}
// Update all organizations to set the form login disabled configuration
// This happens whether the env var is present or not, defaulting to false
mongoTemplate.updateMulti(
new Query(),
new Update().set("organizationConfiguration.isFormLoginEnabled", !formLoginDisabled),
Organization.class);
}
}

View File

@ -0,0 +1,52 @@
package com.appsmith.server.migrations.db.ce;
import com.appsmith.server.configurations.CommonConfig;
import com.appsmith.server.domains.Organization;
import io.mongock.api.annotations.ChangeUnit;
import io.mongock.api.annotations.Execution;
import io.mongock.api.annotations.RollbackExecution;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import java.io.IOException;
import static com.appsmith.server.migrations.db.ce.Migration021MoveGoogleMapsKeyToTenantConfiguration.commentEnvInFile;
@Slf4j
@RequiredArgsConstructor
@ChangeUnit(order = "072", id = "move-signup-disabled-to-organization-configuration")
public class Migration072MoveSignupDisabledToOrganizationConfiguration {
private final MongoTemplate mongoTemplate;
private final CommonConfig commonConfig;
@RollbackExecution
public void rollbackExecution() {}
@Execution
public void executeMigration() throws IOException {
final String envName = "APPSMITH_SIGNUP_DISABLED";
final String signupDisabledValue = System.getenv(envName);
// Default to false if the environment variable is not present or empty
boolean signupDisabled = false;
if (StringUtils.isNotEmpty(signupDisabledValue)) {
// Convert the string value to a boolean if env is present
signupDisabled = Boolean.parseBoolean(signupDisabledValue);
// Comment out the environment variable in the .env file
commentEnvInFile(envName, commonConfig.getEnvFilePath());
}
// Update all organizations to set the signup disabled configuration
// This happens whether the env var is present or not, defaulting to false
mongoTemplate.updateMulti(
new Query(),
new Update().set("organizationConfiguration.isSignupDisabled", signupDisabled),
Organization.class);
}
}

View File

@ -7,7 +7,6 @@ import com.appsmith.server.repositories.AppsmithRepository;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
public interface CustomOrganizationRepositoryCE extends AppsmithRepository<Organization> { public interface CustomOrganizationRepositoryCE extends AppsmithRepository<Organization> {
Mono<Integer> disableRestartForAllOrganizations();
Mono<Organization> findByIdAsUser(User user, String id, AclPermission permission); Mono<Organization> findByIdAsUser(User user, String id, AclPermission permission);
} }

View File

@ -9,20 +9,10 @@ import com.appsmith.server.repositories.BaseAppsmithRepositoryImpl;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import static com.appsmith.server.domains.Organization.Fields.organizationConfiguration_isRestartRequired;
@Slf4j @Slf4j
public class CustomOrganizationRepositoryCEImpl extends BaseAppsmithRepositoryImpl<Organization> public class CustomOrganizationRepositoryCEImpl extends BaseAppsmithRepositoryImpl<Organization>
implements CustomOrganizationRepositoryCE { implements CustomOrganizationRepositoryCE {
@Override
public Mono<Integer> disableRestartForAllOrganizations() {
log.info("Disabling restart for all organizations");
return queryBuilder()
.criteria(Bridge.isTrue(organizationConfiguration_isRestartRequired))
.updateAll(Bridge.update().set(organizationConfiguration_isRestartRequired, false));
}
@Override @Override
public Mono<Organization> findByIdAsUser(User user, String id, AclPermission permission) { public Mono<Organization> findByIdAsUser(User user, String id, AclPermission permission) {
return getAllPermissionGroupsForUser(user).flatMap(permissionGroups -> queryBuilder() return getAllPermissionGroupsForUser(user).flatMap(permissionGroups -> queryBuilder()

View File

@ -2,8 +2,8 @@ package com.appsmith.server.services;
import com.appsmith.server.configurations.CommonConfig; import com.appsmith.server.configurations.CommonConfig;
import com.appsmith.server.helpers.FeatureFlagMigrationHelper; import com.appsmith.server.helpers.FeatureFlagMigrationHelper;
import com.appsmith.server.helpers.InstanceVariablesHelper;
import com.appsmith.server.helpers.UserOrganizationHelper; import com.appsmith.server.helpers.UserOrganizationHelper;
import com.appsmith.server.instanceconfigs.helpers.InstanceVariablesHelper;
import com.appsmith.server.repositories.CacheableRepositoryHelper; import com.appsmith.server.repositories.CacheableRepositoryHelper;
import com.appsmith.server.repositories.OrganizationRepository; import com.appsmith.server.repositories.OrganizationRepository;
import com.appsmith.server.services.ce.OrganizationServiceCEImpl; import com.appsmith.server.services.ce.OrganizationServiceCEImpl;

View File

@ -2,9 +2,9 @@ package com.appsmith.server.services;
import com.appsmith.server.configurations.CommonConfig; import com.appsmith.server.configurations.CommonConfig;
import com.appsmith.server.configurations.EmailConfig; import com.appsmith.server.configurations.EmailConfig;
import com.appsmith.server.helpers.InstanceVariablesHelper;
import com.appsmith.server.helpers.UserServiceHelper; import com.appsmith.server.helpers.UserServiceHelper;
import com.appsmith.server.helpers.UserUtils; import com.appsmith.server.helpers.UserUtils;
import com.appsmith.server.instanceconfigs.helpers.InstanceVariablesHelper;
import com.appsmith.server.notifications.EmailSender; import com.appsmith.server.notifications.EmailSender;
import com.appsmith.server.ratelimiting.RateLimitService; import com.appsmith.server.ratelimiting.RateLimitService;
import com.appsmith.server.repositories.ApplicationRepository; import com.appsmith.server.repositories.ApplicationRepository;

View File

@ -30,7 +30,5 @@ public interface OrganizationServiceCE extends CrudService<Organization, String>
Mono<Organization> retrieveById(String id); Mono<Organization> retrieveById(String id);
Mono<Void> restartOrganization();
Flux<Organization> retrieveAll(); Flux<Organization> retrieveAll();
} }

View File

@ -14,8 +14,8 @@ import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.helpers.CollectionUtils; import com.appsmith.server.helpers.CollectionUtils;
import com.appsmith.server.helpers.FeatureFlagMigrationHelper; import com.appsmith.server.helpers.FeatureFlagMigrationHelper;
import com.appsmith.server.helpers.InstanceVariablesHelper;
import com.appsmith.server.helpers.UserOrganizationHelper; import com.appsmith.server.helpers.UserOrganizationHelper;
import com.appsmith.server.instanceconfigs.helpers.InstanceVariablesHelper;
import com.appsmith.server.repositories.CacheableRepositoryHelper; import com.appsmith.server.repositories.CacheableRepositoryHelper;
import com.appsmith.server.repositories.OrganizationRepository; import com.appsmith.server.repositories.OrganizationRepository;
import com.appsmith.server.services.AnalyticsService; import com.appsmith.server.services.AnalyticsService;
@ -175,8 +175,6 @@ public class OrganizationServiceCEImpl extends BaseService<OrganizationRepositor
config.addThirdPartyAuth("github"); config.addThirdPartyAuth("github");
} }
config.setIsFormLoginEnabled(!"true".equals(System.getenv("APPSMITH_FORM_LOGIN_DISABLED")));
return configService return configService
.getInstanceVariables() .getInstanceVariables()
.map(instanceVariables -> instanceVariablesHelper.populateOrgConfigWithInstanceVariables( .map(instanceVariables -> instanceVariablesHelper.populateOrgConfigWithInstanceVariables(
@ -342,29 +340,6 @@ public class OrganizationServiceCEImpl extends BaseService<OrganizationRepositor
.then(updatedOrganizationMono); .then(updatedOrganizationMono);
} }
/**
* This function checks if the organization needs to be restarted, and executes the restart after the feature flag
* migrations are completed.
*
* @return Mono<Void>
*/
@Override
public Mono<Void> restartOrganization() {
// TODO @CloudBilling: remove this method once we move the form login env to DB variable which is currently
// required as a part of downgrade migration for SSO
return this.retrieveAll()
.filter(organization ->
TRUE.equals(organization.getOrganizationConfiguration().getIsRestartRequired()))
.take(1)
.hasElements()
.flatMap(hasElement -> {
if (hasElement) {
return repository.disableRestartForAllOrganizations().then(envManager.restartWithoutAclCheck());
}
return Mono.empty();
});
}
private boolean isMigrationRequired(Organization organization) { private boolean isMigrationRequired(Organization organization) {
return organization.getOrganizationConfiguration() != null return organization.getOrganizationConfiguration() != null
&& (!CollectionUtils.isNullOrEmpty( && (!CollectionUtils.isNullOrEmpty(

View File

@ -22,9 +22,9 @@ import com.appsmith.server.dtos.UserSignupDTO;
import com.appsmith.server.dtos.UserUpdateDTO; import com.appsmith.server.dtos.UserUpdateDTO;
import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.helpers.InstanceVariablesHelper;
import com.appsmith.server.helpers.UserServiceHelper; import com.appsmith.server.helpers.UserServiceHelper;
import com.appsmith.server.helpers.UserUtils; import com.appsmith.server.helpers.UserUtils;
import com.appsmith.server.instanceconfigs.helpers.InstanceVariablesHelper;
import com.appsmith.server.ratelimiting.RateLimitService; import com.appsmith.server.ratelimiting.RateLimitService;
import com.appsmith.server.repositories.EmailVerificationTokenRepository; import com.appsmith.server.repositories.EmailVerificationTokenRepository;
import com.appsmith.server.repositories.PasswordResetTokenRepository; import com.appsmith.server.repositories.PasswordResetTokenRepository;
@ -557,17 +557,20 @@ public class UserServiceCEImpl extends BaseService<UserRepository, User, String>
*/ */
@Override @Override
public Mono<User> signupIfAllowed(User user) { public Mono<User> signupIfAllowed(User user) {
boolean isAdminUser = false; Mono<Boolean> isAdminUserMono;
if (!commonConfig.getAdminEmails().contains(user.getEmail())) { if (!commonConfig.getAdminEmails().contains(user.getEmail())) {
// If this is not an admin email address, only then do we check if signup should be allowed or not. Being an // If this is not an admin email address, only then do we check if signup should be allowed or not. Being an
// explicitly set admin email address trumps all everything and signup for this email can never be disabled. // explicitly set admin email address trumps all everything and signup for this email can never be disabled.
isAdminUserMono = organizationService.getCurrentUserOrganization().map(organization -> {
if (commonConfig.isSignupDisabled()) { OrganizationConfiguration organizationConfiguration =
organization.getOrganizationConfiguration() == null
? new OrganizationConfiguration()
: organization.getOrganizationConfiguration();
if (TRUE.equals(organizationConfiguration.getIsSignupDisabled())) {
// Signing up has been globally disabled. Reject. // Signing up has been globally disabled. Reject.
return Mono.error(new AppsmithException(AppsmithError.SIGNUP_DISABLED, user.getUsername())); throw new AppsmithException(AppsmithError.SIGNUP_DISABLED, user.getUsername());
} }
final List<String> allowedDomains = user.getSource() == LoginSource.FORM final List<String> allowedDomains = user.getSource() == LoginSource.FORM
? commonConfig.getAllowedDomains() ? commonConfig.getAllowedDomains()
: commonConfig.getOauthAllowedDomains(); : commonConfig.getOauthAllowedDomains();
@ -575,19 +578,21 @@ public class UserServiceCEImpl extends BaseService<UserRepository, User, String>
&& StringUtils.hasText(user.getEmail()) && StringUtils.hasText(user.getEmail())
&& user.getEmail().contains("@") && user.getEmail().contains("@")
&& !allowedDomains.contains(user.getEmail().split("@")[1])) { && !allowedDomains.contains(user.getEmail().split("@")[1])) {
// There is an explicit whitelist of email address domains that should be allowed. If the new email is // There is an explicit whitelist of email address domains that should be allowed. If the new email
// is
// of a different domain, reject. // of a different domain, reject.
return Mono.error(new AppsmithException(AppsmithError.SIGNUP_DISABLED, user.getUsername())); throw new AppsmithException(AppsmithError.SIGNUP_DISABLED, user.getUsername());
} }
return FALSE;
});
} else { } else {
isAdminUser = true; isAdminUserMono = Mono.just(true);
} }
// First set the organization ID for the user // No special configurations found, allow signup for the new user.
boolean finalIsAdminUser = isAdminUser;
return setOrganizationIdForUser(user) return setOrganizationIdForUser(user)
// Then proceed with user creation .zipWhen(userWithOrgId -> isAdminUserMono)
.flatMap(userWithOrgId -> userCreate(userWithOrgId, finalIsAdminUser)) .flatMap(tuple2 -> userCreate(tuple2.getT1(), tuple2.getT2()))
.elapsed() .elapsed()
.map(pair -> { .map(pair -> {
log.debug("UserServiceCEImpl::Time taken for create user: {} ms", pair.getT1()); log.debug("UserServiceCEImpl::Time taken for create user: {} ms", pair.getT1());
@ -826,8 +831,7 @@ public class UserServiceCEImpl extends BaseService<UserRepository, User, String>
return instanceVariablesHelper.isEmailVerificationEnabled().flatMap(emailVerificationEnabled -> { return instanceVariablesHelper.isEmailVerificationEnabled().flatMap(emailVerificationEnabled -> {
// Email verification not enabled at instance level // Email verification not enabled at instance level
if (!TRUE.equals(emailVerificationEnabled)) { if (!TRUE.equals(emailVerificationEnabled)) {
return Mono.error( return Mono.error(new AppsmithException(AppsmithError.EMAIL_VERIFICATION_NOT_ENABLED));
new AppsmithException(AppsmithError.ORGANIZATION_EMAIL_VERIFICATION_NOT_ENABLED));
} }
return emailVerificationTokenRepository return emailVerificationTokenRepository
.findByEmail(user.getEmail()) .findByEmail(user.getEmail())

View File

@ -1,9 +1,9 @@
package com.appsmith.server.services.ce_compatible; package com.appsmith.server.services.ce_compatible;
import com.appsmith.server.configurations.CommonConfig; import com.appsmith.server.configurations.CommonConfig;
import com.appsmith.server.helpers.InstanceVariablesHelper;
import com.appsmith.server.helpers.UserServiceHelper; import com.appsmith.server.helpers.UserServiceHelper;
import com.appsmith.server.helpers.UserUtils; import com.appsmith.server.helpers.UserUtils;
import com.appsmith.server.instanceconfigs.helpers.InstanceVariablesHelper;
import com.appsmith.server.ratelimiting.RateLimitService; import com.appsmith.server.ratelimiting.RateLimitService;
import com.appsmith.server.repositories.EmailVerificationTokenRepository; import com.appsmith.server.repositories.EmailVerificationTokenRepository;
import com.appsmith.server.repositories.PasswordResetTokenRepository; import com.appsmith.server.repositories.PasswordResetTokenRepository;

View File

@ -83,7 +83,6 @@ import static com.appsmith.server.constants.EnvVariables.APPSMITH_RECAPTCHA_SECR
import static com.appsmith.server.constants.EnvVariables.APPSMITH_RECAPTCHA_SITE_KEY; import static com.appsmith.server.constants.EnvVariables.APPSMITH_RECAPTCHA_SITE_KEY;
import static com.appsmith.server.constants.EnvVariables.APPSMITH_REPLY_TO; import static com.appsmith.server.constants.EnvVariables.APPSMITH_REPLY_TO;
import static com.appsmith.server.constants.EnvVariables.APPSMITH_SIGNUP_ALLOWED_DOMAINS; import static com.appsmith.server.constants.EnvVariables.APPSMITH_SIGNUP_ALLOWED_DOMAINS;
import static com.appsmith.server.constants.EnvVariables.APPSMITH_SIGNUP_DISABLED;
import static java.lang.Boolean.TRUE; import static java.lang.Boolean.TRUE;
@Slf4j @Slf4j
@ -371,10 +370,6 @@ public class EnvManagerCEImpl implements EnvManagerCE {
// Try and update any at runtime, that can be. // Try and update any at runtime, that can be.
final Map<String, String> changesCopy = new HashMap<>(changes); final Map<String, String> changesCopy = new HashMap<>(changes);
if (changesCopy.containsKey(APPSMITH_SIGNUP_DISABLED.name())) {
commonConfig.setSignupDisabled(changesCopy.remove(APPSMITH_SIGNUP_DISABLED.name()));
}
if (changesCopy.containsKey(APPSMITH_SIGNUP_ALLOWED_DOMAINS.name())) { if (changesCopy.containsKey(APPSMITH_SIGNUP_ALLOWED_DOMAINS.name())) {
commonConfig.setAllowedDomainsString( commonConfig.setAllowedDomainsString(
changesCopy.remove(APPSMITH_SIGNUP_ALLOWED_DOMAINS.name())); changesCopy.remove(APPSMITH_SIGNUP_ALLOWED_DOMAINS.name()));

View File

@ -39,7 +39,6 @@ public class ScheduledTaskCEImpl implements ScheduledTaskCE {
log.error("Error while fetching organization feature flags", error); log.error("Error while fetching organization feature flags", error);
return Flux.empty(); return Flux.empty();
}) })
.then(organizationService.restartOrganization())
.subscribeOn(LoadShifter.elasticScheduler) .subscribeOn(LoadShifter.elasticScheduler)
.subscribe(); .subscribe();
} }

View File

@ -1,7 +1,7 @@
package com.appsmith.server.helpers.ce; package com.appsmith.server.instanceconfigs.helpers.ce;
import com.appsmith.server.constants.Appsmith; import com.appsmith.server.constants.Appsmith;
import com.appsmith.server.helpers.InstanceVariablesHelper; import com.appsmith.server.instanceconfigs.helpers.InstanceVariablesHelper;
import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.ConfigService;
import net.minidev.json.JSONObject; import net.minidev.json.JSONObject;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;

View File

@ -693,7 +693,7 @@ public class UserServiceTest {
Mono<Boolean> resultMono = userMono.then(organizationMono).then(emailVerificationMono); Mono<Boolean> resultMono = userMono.then(organizationMono).then(emailVerificationMono);
StepVerifier.create(resultMono) StepVerifier.create(resultMono)
.expectErrorMessage(AppsmithError.ORGANIZATION_EMAIL_VERIFICATION_NOT_ENABLED.getMessage()) .expectErrorMessage(AppsmithError.EMAIL_VERIFICATION_NOT_ENABLED.getMessage())
.verify(); .verify();
} }

View File

@ -4,6 +4,8 @@ import com.appsmith.server.applications.base.ApplicationService;
import com.appsmith.server.configurations.CommonConfig; import com.appsmith.server.configurations.CommonConfig;
import com.appsmith.server.configurations.WithMockAppsmithUser; import com.appsmith.server.configurations.WithMockAppsmithUser;
import com.appsmith.server.domains.LoginSource; import com.appsmith.server.domains.LoginSource;
import com.appsmith.server.domains.Organization;
import com.appsmith.server.domains.OrganizationConfiguration;
import com.appsmith.server.domains.User; import com.appsmith.server.domains.User;
import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.exceptions.AppsmithException;
@ -12,6 +14,7 @@ import com.appsmith.server.repositories.PermissionGroupRepository;
import com.appsmith.server.repositories.UserRepository; import com.appsmith.server.repositories.UserRepository;
import com.appsmith.server.repositories.WorkspaceRepository; import com.appsmith.server.repositories.WorkspaceRepository;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
@ -54,16 +57,32 @@ public class UserServiceWithDisabledSignupTest {
@SpyBean @SpyBean
CommonConfig commonConfig; CommonConfig commonConfig;
@Autowired
OrganizationService organizationService;
Mono<User> userMono; Mono<User> userMono;
@BeforeEach @BeforeEach
public void setup() { public void setup() {
userMono = userService.findByEmail("usertest@usertest.com"); userMono = userService.findByEmail("usertest@usertest.com");
Mockito.when(commonConfig.isSignupDisabled()).thenReturn(Boolean.TRUE); Organization organization =
organizationService.getCurrentUserOrganization().block();
assert organization != null;
organization.getOrganizationConfiguration().setIsSignupDisabled(true);
organizationService.save(organization).block();
Mockito.when(commonConfig.getAdminEmails()) Mockito.when(commonConfig.getAdminEmails())
.thenReturn(Set.of("dummy_admin@appsmith.com", "dummy2@appsmith.com")); .thenReturn(Set.of("dummy_admin@appsmith.com", "dummy2@appsmith.com"));
} }
@AfterAll
public static void cleanup(@Autowired OrganizationService organizationService) {
OrganizationConfiguration organizationConfiguration = new OrganizationConfiguration();
organizationConfiguration.setIsSignupDisabled(false);
Organization organization =
organizationService.getCurrentUserOrganization().block();
organizationService.save(organization).block();
}
@Test @Test
@WithMockAppsmithUser @WithMockAppsmithUser
public void createNewUserValidWhenDisabled() { public void createNewUserValidWhenDisabled() {

View File

@ -20,9 +20,6 @@ APPSMITH_CLOUD_SERVICES_BASE_URL="https://release-cs.appsmith.com"
#APPSMITH_OAUTH2_GITHUB_CLIENT_ID="" #APPSMITH_OAUTH2_GITHUB_CLIENT_ID=""
#APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET="" #APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET=""
#APPSMITH_FORM_LOGIN_DISABLED=
#APPSMITH_SIGNUP_DISABLED=
#APPSMITH_SENTRY_DSN= #APPSMITH_SENTRY_DSN=
#APPSMITH_SENTRY_ENVIRONMENT= #APPSMITH_SENTRY_ENVIRONMENT=

View File

@ -4,8 +4,6 @@
# APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET="" # APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET=""
# APPSMITH_OAUTH2_GITHUB_CLIENT_ID="" # APPSMITH_OAUTH2_GITHUB_CLIENT_ID=""
# APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET="" # APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET=""
# APPSMITH_FORM_LOGIN_DISABLED=
# APPSMITH_SIGNUP_DISABLED=
# APPSMITH_MAIL_ENABLED=true # APPSMITH_MAIL_ENABLED=true
# APPSMITH_MAIL_HOST=localhost # APPSMITH_MAIL_HOST=localhost

View File

@ -22,9 +22,6 @@ APPSMITH_CLOUD_SERVICES_BASE_URL="https://release-cs.appsmith.com"
#APPSMITH_OAUTH2_GITHUB_CLIENT_ID="" #APPSMITH_OAUTH2_GITHUB_CLIENT_ID=""
#APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET="" #APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET=""
#APPSMITH_FORM_LOGIN_DISABLED=
#APPSMITH_SIGNUP_DISABLED=
#APPSMITH_SENTRY_DSN= #APPSMITH_SENTRY_DSN=
#APPSMITH_SENTRY_ENVIRONMENT= #APPSMITH_SENTRY_ENVIRONMENT=