diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonConfig.java index 9ff767657283..ee5db6e6a36a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonConfig.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonConfig.java @@ -148,6 +148,7 @@ public Long getCurrentTimeInstantEpochMilli() { return Instant.now().toEpochMilli(); } + @Deprecated(forRemoval = true) public String getAdminEmailDomainHash() { if (StringUtils.hasLength(adminEmailDomainHash)) { return adminEmailDomainHash; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ce/FieldNameCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ce/FieldNameCE.java index 4f091e9cb59c..feb6fd37a1cf 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ce/FieldNameCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ce/FieldNameCE.java @@ -204,4 +204,5 @@ public class FieldNameCE { public static final String ARTIFACT_CONTEXT = "artifactContext"; public static final String ARTIFACT_ID = "artifactId"; public static final String BODY = "body"; + public static final String INSTANCE_ADMIN_CONFIG = "instanceAdminConfig"; } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/InstanceAdminMetaDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/InstanceAdminMetaDTO.java new file mode 100644 index 000000000000..fe33df53a5f1 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/InstanceAdminMetaDTO.java @@ -0,0 +1,47 @@ +package com.appsmith.server.dtos; + +import com.appsmith.server.helpers.HashUtils; +import lombok.Data; +import net.minidev.json.JSONObject; + +import java.util.Optional; + +@Data +public class InstanceAdminMetaDTO { + String email; + String emailDomainHash; + + static final String EMAIL = "email"; + static final String EMAIL_DOMAIN_HASH = "emailDomainHash"; + + /** + * Converts an email address to a JSONObject containing the email and its domain hash. + * @param email The email address to convert + * @return A JSONObject containing the email and its domain hash + */ + public static JSONObject toJsonObject(String email) { + email = email == null ? "" : email; + JSONObject jsonObject = new JSONObject(); + jsonObject.put(EMAIL, email); + jsonObject.put(EMAIL_DOMAIN_HASH, HashUtils.getEmailDomainHash(email)); + return jsonObject; + } + + /** + * Creates an InstanceAdminMetaDTO from a JSONObject. + * @param jsonObject The JSONObject containing email and emailDomainHash + * @return An InstanceAdminMetaDTO populated with data from the JSONObject + */ + public static InstanceAdminMetaDTO fromJsonObject(JSONObject jsonObject) { + if (jsonObject == null) { + return new InstanceAdminMetaDTO(); + } + InstanceAdminMetaDTO instanceAdminMetaDTO = new InstanceAdminMetaDTO(); + instanceAdminMetaDTO.setEmail( + Optional.ofNullable(jsonObject.get(EMAIL)).map(Object::toString).orElse("")); + instanceAdminMetaDTO.setEmailDomainHash(Optional.ofNullable(jsonObject.get(EMAIL_DOMAIN_HASH)) + .map(Object::toString) + .orElse("")); + return instanceAdminMetaDTO; + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/HashUtils.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/HashUtils.java new file mode 100644 index 000000000000..1a4549eb4148 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/HashUtils.java @@ -0,0 +1,19 @@ +package com.appsmith.server.helpers; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; + +public class HashUtils { + + public static String hash(String value) { + return StringUtils.isEmpty(value) ? "" : DigestUtils.sha256Hex(value); + } + + public static String getEmailDomainHash(String email) { + if (email == null) { + return ""; + } + + return hash(email.contains("@") ? email.split("@", 2)[1] : ""); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java index e64c40776015..6e4c8202900d 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java @@ -24,6 +24,7 @@ import com.appsmith.server.domains.UsagePulse; import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; +import com.appsmith.server.dtos.InstanceAdminMetaDTO; import com.appsmith.server.dtos.Permission; import com.appsmith.server.helpers.TextUtils; import com.appsmith.server.migrations.solutions.UpdateSuperUserMigrationHelper; @@ -45,6 +46,7 @@ import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.redis.core.ReactiveRedisOperations; import org.springframework.util.StreamUtils; +import org.springframework.util.StringUtils; import java.io.IOException; import java.nio.charset.Charset; @@ -65,12 +67,14 @@ import static com.appsmith.server.constants.EnvVariables.APPSMITH_ADMIN_EMAILS; import static com.appsmith.server.constants.FieldName.DEFAULT_PERMISSION_GROUP; import static com.appsmith.server.constants.FieldName.PERMISSION_GROUP_ID; +import static com.appsmith.server.constants.ce.FieldNameCE.INSTANCE_ADMIN_CONFIG; import static com.appsmith.server.helpers.CollectionUtils.findSymmetricDiff; import static com.appsmith.server.migrations.DatabaseChangelog1.dropIndexIfExists; import static com.appsmith.server.migrations.DatabaseChangelog1.ensureIndexes; import static com.appsmith.server.migrations.DatabaseChangelog1.installPluginToAllWorkspaces; import static com.appsmith.server.migrations.DatabaseChangelog1.makeIndex; import static com.appsmith.server.migrations.MigrationHelperMethods.evictPermissionCacheForUsers; +import static com.appsmith.server.migrations.db.ce.Migration064AddInstanceAdminDetailsToDB.verifyIfInstanceAdminDetailsArePresent; import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Query.query; import static org.springframework.data.mongodb.core.query.Update.update; @@ -503,6 +507,21 @@ public void updateSuperUsers( Update update = new Update().set(PermissionGroup.Fields.assignedToUserIds, userIds); mongoTemplate.updateFirst(permissionGroupQuery, update, PermissionGroup.class); + + // Check if instance admin details are already present in the DB + if (verifyIfInstanceAdminDetailsArePresent(mongoTemplate)) { + return; + } + String adminEmail = adminEmails.stream() + .filter(email -> email != null && email.contains("@")) + .findFirst() + .orElse(null); + Config config = new Config(); + config.setName(INSTANCE_ADMIN_CONFIG); + if (StringUtils.hasLength(adminEmail)) { + config.setConfig(InstanceAdminMetaDTO.toJsonObject(adminEmail)); + mongoTemplate.save(config); + } } @ChangeSet(order = "034", id = "update-bad-theme-state", author = "") diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/constants/FieldName.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/constants/FieldName.java index ee6fe668ced7..e6e8fd587441 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/constants/FieldName.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/constants/FieldName.java @@ -5,4 +5,5 @@ public class FieldName { public static final String DELETED_AT = "deletedAt"; public static final String TENANT_ID = "tenantId"; public static final String PERMISSION_GROUPS = "permissionGroups"; + public static final String DEFAULT_CLOUD_ADMIN_EMAIL = "admin@appsmith.com"; } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration064AddInstanceAdminDetailsToDB.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration064AddInstanceAdminDetailsToDB.java new file mode 100644 index 000000000000..a2e802dea9aa --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration064AddInstanceAdminDetailsToDB.java @@ -0,0 +1,100 @@ +package com.appsmith.server.migrations.db.ce; + +import com.appsmith.server.configurations.CommonConfig; +import com.appsmith.server.constants.FieldName; +import com.appsmith.server.domains.Config; +import com.appsmith.server.domains.PermissionGroup; +import com.appsmith.server.domains.User; +import com.appsmith.server.dtos.InstanceAdminMetaDTO; +import com.appsmith.server.helpers.CollectionUtils; +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.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.util.StringUtils; +import reactor.core.publisher.Flux; + +import static com.appsmith.server.constants.ce.FieldNameCE.INSTANCE_ADMIN_CONFIG; +import static com.appsmith.server.helpers.ce.bridge.BridgeQuery.where; +import static com.appsmith.server.migrations.constants.FieldName.DEFAULT_CLOUD_ADMIN_EMAIL; +import static com.appsmith.server.repositories.ce.BaseAppsmithRepositoryCEImpl.notDeleted; + +@RequiredArgsConstructor +@Slf4j +@ChangeUnit(order = "064", id = "add_instance_admin_details_to_config_collection") +public class Migration064AddInstanceAdminDetailsToDB { + + private final MongoTemplate mongoTemplate; + private final CommonConfig commonConfig; + + @RollbackExecution + public void rollbackExecution() {} + + @Execution + public void executeMigration() { + // Add instance admin details to the DB + // This migration is idempotent and can be run multiple times without any side effects + log.info("Adding instance admin details to the DB"); + // Check if instance admin details are already present in the DB to make the migration idempotent + if (verifyIfInstanceAdminDetailsArePresent(mongoTemplate)) { + return; + } + + // Add instance admin details to the DB + Query instanceAdminRoleQuery = new Query() + .addCriteria(where(FieldName.NAME).is(FieldName.INSTANCE_ADMIN_ROLE)) + .addCriteria(notDeleted()); + PermissionGroup instanceAdminPG = mongoTemplate.findOne(instanceAdminRoleQuery, PermissionGroup.class); + if (instanceAdminPG == null) { + log.error("Instance admin permission group not found in the DB. Skipping migration 064"); + return; + } + String adminEmail = null; + if (commonConfig.isCloudHosting()) { + // As a fallback, use the default admin email for cloud hosting + adminEmail = DEFAULT_CLOUD_ADMIN_EMAIL; + } else if (!CollectionUtils.isNullOrEmpty(instanceAdminPG.getAssignedToUserIds())) { + adminEmail = Flux.fromIterable(instanceAdminPG.getAssignedToUserIds()) + .map(userId -> { + User user = mongoTemplate.findOne( + new Query() + .addCriteria(where(FieldName.ID).is(userId)) + .addCriteria(notDeleted()), + User.class); + return user != null ? user.getEmail() : ""; + }) + .filter(email -> email != null && email.contains("@")) + .blockFirst(); + } + + if (!StringUtils.hasLength(adminEmail)) { + adminEmail = commonConfig.getAdminEmails().stream() + .filter(email -> email != null && email.contains("@")) + .findFirst() + .orElse(null); + } + Config config = new Config(); + config.setName(INSTANCE_ADMIN_CONFIG); + if (StringUtils.hasLength(adminEmail)) { + config.setConfig(InstanceAdminMetaDTO.toJsonObject(adminEmail)); + mongoTemplate.save(config); + } + } + + public static boolean verifyIfInstanceAdminDetailsArePresent(MongoTemplate mongoTemplate) { + Query instanceAdminConfigQuery = new Query() + .addCriteria(where(FieldName.NAME).is(FieldName.INSTANCE_ADMIN_CONFIG)) + .addCriteria(notDeleted()); + Config instanceAdminConfig = mongoTemplate.findOne(instanceAdminConfigQuery, Config.class); + boolean adminDetailsPresent = instanceAdminConfig != null + && StringUtils.hasLength(InstanceAdminMetaDTO.fromJsonObject(instanceAdminConfig.getConfig()) + .getEmail()); + if (adminDetailsPresent) { + log.info("Instance admin details already present in the DB. Skipping migration 64"); + } + return adminDetailsPresent; + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/TenantServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/TenantServiceImpl.java index 53fdf6b1be7f..021839bd0d4b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/TenantServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/TenantServiceImpl.java @@ -1,6 +1,5 @@ package com.appsmith.server.services; -import com.appsmith.server.configurations.CommonConfig; import com.appsmith.server.helpers.FeatureFlagMigrationHelper; import com.appsmith.server.repositories.CacheableRepositoryHelper; import com.appsmith.server.repositories.TenantRepository; @@ -22,7 +21,6 @@ public TenantServiceImpl( @Lazy EnvManager envManager, FeatureFlagMigrationHelper featureFlagMigrationHelper, CacheableRepositoryHelper cacheableRepositoryHelper, - CommonConfig commonConfig, ObservationRegistry observationRegistry) { super( validator, @@ -32,7 +30,6 @@ public TenantServiceImpl( envManager, featureFlagMigrationHelper, cacheableRepositoryHelper, - commonConfig, observationRegistry); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/AnalyticsServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/AnalyticsServiceCEImpl.java index 8c41a2fc8514..c16b67dc7753 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/AnalyticsServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/AnalyticsServiceCEImpl.java @@ -8,9 +8,11 @@ import com.appsmith.server.configurations.DeploymentProperties; import com.appsmith.server.configurations.ProjectProperties; import com.appsmith.server.constants.FieldName; +import com.appsmith.server.domains.Config; import com.appsmith.server.domains.NewPage; import com.appsmith.server.domains.User; import com.appsmith.server.domains.UserData; +import com.appsmith.server.dtos.InstanceAdminMetaDTO; import com.appsmith.server.helpers.ExchangeUtils; import com.appsmith.server.helpers.UserUtils; import com.appsmith.server.repositories.UserDataRepository; @@ -20,7 +22,6 @@ import com.segment.analytics.messages.IdentifyMessage; import com.segment.analytics.messages.TrackMessage; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -37,9 +38,12 @@ import static com.appsmith.external.constants.AnalyticsConstants.IP; import static com.appsmith.external.constants.AnalyticsConstants.IP_ADDRESS; import static com.appsmith.server.constants.ce.FieldNameCE.EMAIL; +import static com.appsmith.server.constants.ce.FieldNameCE.INSTANCE_ADMIN_CONFIG; import static com.appsmith.server.constants.ce.FieldNameCE.NAME; import static com.appsmith.server.constants.ce.FieldNameCE.PROFICIENCY; import static com.appsmith.server.constants.ce.FieldNameCE.ROLE; +import static com.appsmith.server.helpers.HashUtils.getEmailDomainHash; +import static com.appsmith.server.helpers.HashUtils.hash; @Slf4j public class AnalyticsServiceCEImpl implements AnalyticsServiceCE { @@ -56,6 +60,8 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE { private final UserDataRepository userDataRepository; + private static String adminEmailDomainHash; + @Autowired public AnalyticsServiceCEImpl( @Autowired(required = false) Analytics analytics, @@ -80,18 +86,6 @@ public boolean isActive() { return analytics != null; } - private String hash(String value) { - return StringUtils.isEmpty(value) ? "" : DigestUtils.sha256Hex(value); - } - - private String getEmailDomainHash(String email) { - if (email == null) { - return ""; - } - - return hash(email.contains("@") ? email.split("@", 2)[1] : ""); - } - @Override public Mono identifyUser(User user, UserData userData) { return identifyUser(user, userData, null); @@ -230,14 +224,31 @@ public Mono sendEvent(String event, String userId, Map properti final String finalUserId = userId; + Mono instanceAdminEmailDomainMono = adminEmailDomainHash != null + ? Mono.just(adminEmailDomainHash) + : configService + .getByName(INSTANCE_ADMIN_CONFIG) + .onErrorResume(e -> Mono.empty()) + .switchIfEmpty(Mono.just(new Config())) + .map(config -> { + if (config.getConfig() == null) { + return ""; + } + adminEmailDomainHash = InstanceAdminMetaDTO.fromJsonObject(config.getConfig()) + .getEmailDomainHash(); + return adminEmailDomainHash; + }); + return Mono.zip( ExchangeUtils.getAnonymousUserIdFromCurrentRequest(), ExchangeUtils.getUserAgentFromCurrentRequest(), - configService.getInstanceId().defaultIfEmpty("unknown-instance-id")) + configService.getInstanceId().defaultIfEmpty("unknown-instance-id"), + instanceAdminEmailDomainMono) .map(tuple -> { final String userIdFromClient = tuple.getT1(); final String userAgent = tuple.getT2(); final String instanceId = tuple.getT3(); + final String instanceAdminDomainHash = ObjectUtils.defaultIfNull(tuple.getT4(), ""); String userIdToSend = finalUserId; if (FieldName.ANONYMOUS_USER.equals(finalUserId)) { userIdToSend = StringUtils.defaultIfEmpty(userIdFromClient, FieldName.ANONYMOUS_USER); @@ -259,7 +270,7 @@ public Mono sendEvent(String event, String userId, Map properti analyticsProperties.put(ADMIN_EMAIL_DOMAIN_HASH, domainHash); } else { analyticsProperties.put(EMAIL_DOMAIN_HASH, emailDomainHash); - analyticsProperties.put(ADMIN_EMAIL_DOMAIN_HASH, commonConfig.getAdminEmailDomainHash()); + analyticsProperties.put(ADMIN_EMAIL_DOMAIN_HASH, instanceAdminDomainHash); } analyticsProperties.put("originService", "appsmith-server"); analyticsProperties.put("instanceId", instanceId); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceCEImpl.java index 1f046c8ba290..2328f259a54b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceCEImpl.java @@ -172,8 +172,8 @@ public Mono getConsolidatedInfoForPageLoad( /* Get tenant config data */ fetches.add(tenantService .getTenantConfiguration() - .as(this::toResponseDTO) .doOnError(e -> log.error("Error fetching tenant config", e)) + .as(this::toResponseDTO) .doOnSuccess(consolidatedAPIResponseDTO::setTenantConfig) .name(getQualifiedSpanName(TENANT_SPAN, mode)) .tap(Micrometer.observation(observationRegistry))); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCEImpl.java index d37b761f1aba..655c8cceffe9 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCEImpl.java @@ -3,12 +3,13 @@ import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.external.helpers.AppsmithBeanUtils; import com.appsmith.server.acl.AclPermission; -import com.appsmith.server.configurations.CommonConfig; import com.appsmith.server.constants.FeatureMigrationType; import com.appsmith.server.constants.FieldName; import com.appsmith.server.constants.MigrationStatus; +import com.appsmith.server.domains.Config; import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.TenantConfiguration; +import com.appsmith.server.dtos.InstanceAdminMetaDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.CollectionUtils; @@ -32,6 +33,7 @@ import static com.appsmith.external.constants.spans.TenantSpan.FETCH_DEFAULT_TENANT_SPAN; import static com.appsmith.external.constants.spans.TenantSpan.FETCH_TENANT_CACHE_POST_DESERIALIZATION_ERROR_SPAN; import static com.appsmith.server.acl.AclPermission.MANAGE_TENANT; +import static com.appsmith.server.constants.ce.FieldNameCE.INSTANCE_ADMIN_CONFIG; import static java.lang.Boolean.TRUE; @Slf4j @@ -47,7 +49,6 @@ public class TenantServiceCEImpl extends BaseService findById(String tenantId, AclPermission permission) { @Override public Mono getTenantConfiguration(Mono dbTenantMono) { - String adminEmailDomainHash = commonConfig.getAdminEmailDomainHash(); - Mono clientTenantMono = configService.getInstanceId().map(instanceId -> { - final Tenant tenant = new Tenant(); - tenant.setInstanceId(instanceId); - tenant.setAdminEmailDomainHash(adminEmailDomainHash); + Mono instanceAdminEmailDomainMono = configService + .getByName(INSTANCE_ADMIN_CONFIG) + .onErrorResume(e -> Mono.empty()) + .switchIfEmpty(Mono.just(new Config())) + .map(config -> { + if (config.getConfig() == null) { + return ""; + } + return InstanceAdminMetaDTO.fromJsonObject(config.getConfig()) + .getEmailDomainHash(); + }); + Mono clientTenantMono = configService + .getInstanceId() + .zipWith(instanceAdminEmailDomainMono) + .map(tuple2 -> { + final Tenant tenant = new Tenant(); + tenant.setInstanceId(tuple2.getT1()); + tenant.setAdminEmailDomainHash(tuple2.getT2()); - final TenantConfiguration config = new TenantConfiguration(); - tenant.setTenantConfiguration(config); + final TenantConfiguration config = new TenantConfiguration(); + tenant.setTenantConfiguration(config); - config.setGoogleMapsKey(System.getenv("APPSMITH_GOOGLE_MAPS_API_KEY")); + config.setGoogleMapsKey(System.getenv("APPSMITH_GOOGLE_MAPS_API_KEY")); - if (StringUtils.hasText(System.getenv("APPSMITH_OAUTH2_GOOGLE_CLIENT_ID"))) { - config.addThirdPartyAuth("google"); - } + if (StringUtils.hasText(System.getenv("APPSMITH_OAUTH2_GOOGLE_CLIENT_ID"))) { + config.addThirdPartyAuth("google"); + } - if (StringUtils.hasText(System.getenv("APPSMITH_OAUTH2_GITHUB_CLIENT_ID"))) { - config.addThirdPartyAuth("github"); - } + if (StringUtils.hasText(System.getenv("APPSMITH_OAUTH2_GITHUB_CLIENT_ID"))) { + config.addThirdPartyAuth("github"); + } - config.setIsFormLoginEnabled(!"true".equals(System.getenv("APPSMITH_FORM_LOGIN_DISABLED"))); + config.setIsFormLoginEnabled(!"true".equals(System.getenv("APPSMITH_FORM_LOGIN_DISABLED"))); - return tenant; - }); + return tenant; + }); return Mono.zip(dbTenantMono, clientTenantMono).flatMap(tuple -> { Tenant dbTenant = tuple.getT1(); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PingScheduledTaskCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PingScheduledTaskCEImpl.java index f33982a7d160..cc25f6a74857 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PingScheduledTaskCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PingScheduledTaskCEImpl.java @@ -5,6 +5,8 @@ import com.appsmith.server.configurations.DeploymentProperties; import com.appsmith.server.configurations.ProjectProperties; import com.appsmith.server.configurations.SegmentConfig; +import com.appsmith.server.domains.Config; +import com.appsmith.server.dtos.InstanceAdminMetaDTO; import com.appsmith.server.helpers.NetworkUtils; import com.appsmith.server.repositories.ApplicationRepository; import com.appsmith.server.repositories.DatasourceRepository; @@ -33,6 +35,7 @@ import static com.appsmith.external.constants.AnalyticsConstants.ADMIN_EMAIL_DOMAIN_HASH; import static com.appsmith.external.constants.AnalyticsConstants.EMAIL_DOMAIN_HASH; +import static com.appsmith.server.constants.FieldName.INSTANCE_ADMIN_CONFIG; import static java.util.Map.entry; import static org.apache.commons.lang3.StringUtils.defaultIfEmpty; @@ -152,23 +155,42 @@ public void pingStats() { userCountMono, getUserTrackingDetails()); + Mono instanceAdminEmailDomainMono = configService + .getByName(INSTANCE_ADMIN_CONFIG) + .onErrorResume(error -> Mono.empty()) + .switchIfEmpty(Mono.just(new Config())) + .map(config -> { + if (config.getConfig() == null) { + return ""; + } + return InstanceAdminMetaDTO.fromJsonObject(config.getConfig()) + .getEmailDomainHash(); + }); + publicPermissionGroupIdMono .flatMap(publicPermissionGroupId -> Mono.zip( configService.getInstanceId().defaultIfEmpty("null"), networkUtils.getExternalAddress(), nonDeletedObjectsCountMono, applicationRepository.getAllApplicationsCountAccessibleToARoleWithPermission( - AclPermission.READ_APPLICATIONS, publicPermissionGroupId))) - .flatMap(statsData -> { + AclPermission.READ_APPLICATIONS, publicPermissionGroupId), + instanceAdminEmailDomainMono)) + .flatMap(tuple5 -> { + final String instanceId = tuple5.getT1(); + final String ipAddress = tuple5.getT2(); + Tuple7> counts = tuple5.getT3(); + Long publicAppsCount = tuple5.getT4(); + String adminEmailDomainHash = tuple5.getT5(); + Map propertiesMap = new java.util.HashMap<>(Map.ofEntries( - entry("instanceId", statsData.getT1()), - entry("numOrgs", statsData.getT3().getT1()), - entry("numApps", statsData.getT3().getT2()), - entry("numPages", statsData.getT3().getT3()), - entry("numActions", statsData.getT3().getT4()), - entry("numDatasources", statsData.getT3().getT5()), - entry("numUsers", statsData.getT3().getT6()), - entry("numPublicApps", statsData.getT4()), + entry("instanceId", instanceId), + entry("numOrgs", counts.getT1()), + entry("numApps", counts.getT2()), + entry("numPages", counts.getT3()), + entry("numActions", counts.getT4()), + entry("numDatasources", counts.getT5()), + entry("numUsers", counts.getT6()), + entry("numPublicApps", publicAppsCount), entry("version", projectProperties.getVersion()), entry("edition", deploymentProperties.getEdition()), entry("cloudProvider", defaultIfEmpty(deploymentProperties.getCloudProvider(), "")), @@ -176,12 +198,11 @@ public void pingStats() { entry("tool", defaultIfEmpty(deploymentProperties.getTool(), "")), entry("hostname", defaultIfEmpty(deploymentProperties.getHostname(), "")), entry("deployedAt", defaultIfEmpty(deploymentProperties.getDeployedAt(), "")), - entry(ADMIN_EMAIL_DOMAIN_HASH, commonConfig.getAdminEmailDomainHash()), - entry(EMAIL_DOMAIN_HASH, commonConfig.getAdminEmailDomainHash()))); + entry(ADMIN_EMAIL_DOMAIN_HASH, defaultIfEmpty(adminEmailDomainHash, "")), + entry(EMAIL_DOMAIN_HASH, defaultIfEmpty(adminEmailDomainHash, "")))); - propertiesMap.putAll(statsData.getT3().getT7()); + propertiesMap.putAll(counts.getT7()); - final String ipAddress = statsData.getT2(); return WebClientUtils.create("https://api.segment.io") .post() .uri("/v1/track") @@ -189,7 +210,7 @@ public void pingStats() { .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(Map.of( "userId", - statsData.getT1(), + tuple5.getT1(), "context", Map.of("ip", ipAddress), "properties", diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/UserSignupCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/UserSignupCEImpl.java index 75133d866d02..5f49015fd4e8 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/UserSignupCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/UserSignupCEImpl.java @@ -3,12 +3,14 @@ import com.appsmith.external.constants.AnalyticsEvents; import com.appsmith.server.authentication.handlers.AuthenticationSuccessHandler; import com.appsmith.server.constants.FieldName; +import com.appsmith.server.domains.Config; import com.appsmith.server.domains.LoginSource; import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.TenantConfiguration; import com.appsmith.server.domains.User; import com.appsmith.server.domains.UserData; import com.appsmith.server.domains.UserState; +import com.appsmith.server.dtos.InstanceAdminMetaDTO; import com.appsmith.server.dtos.UserSignupDTO; import com.appsmith.server.dtos.UserSignupRequestDTO; import com.appsmith.server.exceptions.AppsmithError; @@ -56,6 +58,7 @@ import static com.appsmith.server.constants.Appsmith.DEFAULT_ORIGIN_HEADER; import static com.appsmith.server.constants.EnvVariables.APPSMITH_ADMIN_EMAILS; import static com.appsmith.server.constants.EnvVariables.APPSMITH_DISABLE_TELEMETRY; +import static com.appsmith.server.constants.FieldName.INSTANCE_ADMIN_CONFIG; import static com.appsmith.server.constants.ce.FieldNameCE.DEFAULT; import static com.appsmith.server.constants.ce.FieldNameCE.EMAIL; import static com.appsmith.server.constants.ce.FieldNameCE.NAME; @@ -467,12 +470,20 @@ private Mono sendInstallationSetupAnalytics( newsletterSignedUpUserName, ip); - return analyticsService - .sendEvent( + Config config = new Config(); + config.setName(INSTANCE_ADMIN_CONFIG); + config.setConfig(InstanceAdminMetaDTO.toJsonObject(newsletterSignedUpUserEmail)); + Mono configMono = configService + .getByName(INSTANCE_ADMIN_CONFIG) + .onErrorResume(error -> Mono.empty()) + .switchIfEmpty(configService.save(config)); + + return configMono + .then(analyticsService.sendEvent( AnalyticsEvents.INSTALLATION_SETUP_COMPLETE.getEventName(), instanceId, analyticsProps, - false) + false)) .thenReturn(1L) .elapsed() .map(pair -> {