Skip to content

Commit

Permalink
chore: Add admin email to config DB for quick reference
Browse files Browse the repository at this point in the history
  • Loading branch information
abhvsn committed Sep 28, 2024
1 parent b1ed82d commit a658ac5
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ public Long getCurrentTimeInstantEpochMilli() {
return Instant.now().toEpochMilli();
}

@Deprecated(forRemoval = true)
public String getAdminEmailDomainHash() {
if (StringUtils.hasLength(adminEmailDomainHash)) {
return adminEmailDomainHash;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.appsmith.server.dtos;

import com.appsmith.server.helpers.HashUtils;
import lombok.Data;
import net.minidev.json.JSONObject;

@Data
public class InstanceAdminMetaDTO {
String email;
String emailDomainHash;

public static JSONObject toJsonObject(String email) {
email = email == null ? "" : email;
JSONObject jsonObject = new JSONObject();
jsonObject.put("email", email);
jsonObject.put("emailDomainHash", HashUtils.getEmailDomainHash(email));
return jsonObject;
}

public static InstanceAdminMetaDTO fromJsonObject(JSONObject jsonObject) {
if (jsonObject == null) {
return new InstanceAdminMetaDTO();
}
InstanceAdminMetaDTO instanceAdminMetaDTO = new InstanceAdminMetaDTO();
instanceAdminMetaDTO.setEmail((String) jsonObject.get("email"));
instanceAdminMetaDTO.setEmailDomainHash((String) jsonObject.get("emailDomainHash"));
return instanceAdminMetaDTO;
}
}
Original file line number Diff line number Diff line change
@@ -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] : "");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
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 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.repositories.ce.BaseAppsmithRepositoryCEImpl.notDeleted;

@RequiredArgsConstructor
@Slf4j
@ChangeUnit(order = "063", id = "add_instance_admin_details_to_config_collection")
public class Migration063AddInstanceAdminDetailsToDB {

MongoTemplate mongoTemplate;
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");
// Add instance admin details to the DB
Query query = new Query()
.addCriteria(where(FieldName.NAME).is(FieldName.INSTANCE_ADMIN_ROLE))
.addCriteria(notDeleted());
PermissionGroup instanceAdminPG = mongoTemplate.findOne(query, PermissionGroup.class);
if (instanceAdminPG == null) {
log.error("Instance admin permission group not found in the DB. Skipping migration 63");
return;
}
String adminEmail;
if (!CollectionUtils.isNullOrEmpty(instanceAdminPG.getAssignedToUserIds())) {
adminEmail = Flux.fromIterable(instanceAdminPG.getAssignedToUserIds())
.map(userId -> mongoTemplate.findOne(
new Query()
.addCriteria(where(FieldName.ID).is(userId))
.addCriteria(notDeleted()),
User.class))
.map(User::getEmail)
.filter(email -> email != null && email.contains("@"))
.blockFirst();
} else {
adminEmail = commonConfig.getAdminEmails().stream()
.filter(email -> email != null && email.contains("@"))
.findFirst()
.orElse(null);
}
Config config = new Config();
config.setName(INSTANCE_ADMIN_CONFIG);
config.setConfig(InstanceAdminMetaDTO.toJsonObject(adminEmail));
mongoTemplate.save(config);
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -22,7 +21,6 @@ public TenantServiceImpl(
@Lazy EnvManager envManager,
FeatureFlagMigrationHelper featureFlagMigrationHelper,
CacheableRepositoryHelper cacheableRepositoryHelper,
CommonConfig commonConfig,
ObservationRegistry observationRegistry) {
super(
validator,
Expand All @@ -32,7 +30,6 @@ public TenantServiceImpl(
envManager,
featureFlagMigrationHelper,
cacheableRepositoryHelper,
commonConfig,
observationRegistry);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -80,18 +84,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<User> identifyUser(User user, UserData userData) {
return identifyUser(user, userData, null);
Expand Down Expand Up @@ -230,14 +222,27 @@ public Mono<Void> sendEvent(String event, String userId, Map<String, ?> properti

final String finalUserId = userId;

Mono<String> instanceAdminEmailDomainMono = configService
.getByName(INSTANCE_ADMIN_CONFIG)
.switchIfEmpty(Mono.just(new Config()))
.map(config -> {
if (config.getConfig() == null) {
return "";
}
return InstanceAdminMetaDTO.fromJsonObject(config.getConfig())
.getEmailDomainHash();
});

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);
Expand All @@ -259,7 +264,7 @@ public Mono<Void> sendEvent(String event, String userId, Map<String, ?> 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -47,7 +49,6 @@ public class TenantServiceCEImpl extends BaseService<TenantRepository, Tenant, S

private final CacheableRepositoryHelper cacheableRepositoryHelper;

private final CommonConfig commonConfig;
private final ObservationRegistry observationRegistry;

public TenantServiceCEImpl(
Expand All @@ -58,14 +59,12 @@ public TenantServiceCEImpl(
@Lazy EnvManager envManager,
FeatureFlagMigrationHelper featureFlagMigrationHelper,
CacheableRepositoryHelper cacheableRepositoryHelper,
CommonConfig commonConfig,
ObservationRegistry observationRegistry) {
super(validator, repository, analyticsService);
this.configService = configService;
this.envManager = envManager;
this.featureFlagMigrationHelper = featureFlagMigrationHelper;
this.cacheableRepositoryHelper = cacheableRepositoryHelper;
this.commonConfig = commonConfig;
this.observationRegistry = observationRegistry;
}

Expand Down Expand Up @@ -136,29 +135,41 @@ public Mono<Tenant> findById(String tenantId, AclPermission permission) {

@Override
public Mono<Tenant> getTenantConfiguration(Mono<Tenant> dbTenantMono) {
String adminEmailDomainHash = commonConfig.getAdminEmailDomainHash();
Mono<Tenant> clientTenantMono = configService.getInstanceId().map(instanceId -> {
final Tenant tenant = new Tenant();
tenant.setInstanceId(instanceId);
tenant.setAdminEmailDomainHash(adminEmailDomainHash);
Mono<String> instanceAdminEmailDomainMono = configService
.getByName(INSTANCE_ADMIN_CONFIG)
.switchIfEmpty(Mono.just(new Config()))
.map(config -> {
if (config.getConfig() == null) {
return "";
}
return InstanceAdminMetaDTO.fromJsonObject(config.getConfig())
.getEmailDomainHash();
});
Mono<Tenant> 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();
Expand Down
Loading

0 comments on commit a658ac5

Please sign in to comment.