diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/ProjectProperties.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/ProjectProperties.java index 1c2c1d343f..c9a758a235 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/ProjectProperties.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/ProjectProperties.java @@ -16,6 +16,8 @@ import org.springframework.context.annotation.PropertySource; @Getter public class ProjectProperties { + public static final String EDITION = "CE"; + @Value("${version:UNKNOWN}") private String version; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserDataRepositoryCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserDataRepositoryCE.java index ab07b0bb90..30cd79c97e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserDataRepositoryCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserDataRepositoryCE.java @@ -15,4 +15,7 @@ public interface CustomUserDataRepositoryCE extends AppsmithRepository Mono removeIdFromRecentlyUsedList(String userId, String workspaceId, List applicationIds); Flux findPhotoAssetsByUserIds(Iterable userId); + + Mono fetchMostRecentlyUsedWorkspaceId(String userId); + } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserDataRepositoryCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserDataRepositoryCEImpl.java index c730f78b1d..3fe76c31e3 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserDataRepositoryCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserDataRepositoryCEImpl.java @@ -9,6 +9,7 @@ import com.mongodb.client.result.UpdateResult; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.util.CollectionUtils; import reactor.core.publisher.Flux; @@ -66,4 +67,17 @@ public class CustomUserDataRepositoryCEImpl extends BaseAppsmithRepositoryImpl fetchMostRecentlyUsedWorkspaceId(String userId) { + final Query query = query(where(fieldName(QUserData.userData.userId)).is(userId)); + + query.fields().include(fieldName(QUserData.userData.recentlyUsedWorkspaceIds)); + + return mongoOperations.findOne(query, UserData.class) + .map(userData -> { + final List recentlyUsedWorkspaceIds = userData.getRecentlyUsedWorkspaceIds(); + return CollectionUtils.isEmpty(recentlyUsedWorkspaceIds) ? "" : recentlyUsedWorkspaceIds.get(0); + }); + } + } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/AnalyticsServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/AnalyticsServiceImpl.java index d228220624..c1f48dfd0c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/AnalyticsServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/AnalyticsServiceImpl.java @@ -1,8 +1,10 @@ package com.appsmith.server.services; import com.appsmith.server.configurations.CommonConfig; +import com.appsmith.server.configurations.ProjectProperties; import com.appsmith.server.helpers.PolicyUtils; import com.appsmith.server.helpers.UserUtils; +import com.appsmith.server.repositories.UserDataRepository; import com.appsmith.server.services.ce.AnalyticsServiceCEImpl; import com.google.gson.Gson; import com.segment.analytics.Analytics; @@ -19,12 +21,10 @@ public class AnalyticsServiceImpl extends AnalyticsServiceCEImpl implements Anal SessionUserService sessionUserService, CommonConfig commonConfig, ConfigService configService, - PolicyUtils policyUtils, UserUtils userUtils, - Gson gson) { - - super(analytics, sessionUserService, commonConfig, configService, policyUtils, userUtils, gson); + ProjectProperties projectProperties, + UserDataRepository userDataRepository) { + super(analytics, sessionUserService, commonConfig, configService, userUtils, projectProperties, userDataRepository); } - } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/AnalyticsServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/AnalyticsServiceCE.java index a9de5ccf3d..3d27dd0317 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/AnalyticsServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/AnalyticsServiceCE.java @@ -14,6 +14,8 @@ public interface AnalyticsServiceCE { Mono identifyUser(User user, UserData userData); + Mono identifyUser(User user, UserData userData, String recentlyUsedWorkspaceId); + void identifyInstance(String instanceId, String role, String useCase); Mono sendEvent(String event, String userId, Map properties); 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 a55f5e83ee..9e9c739bd4 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 @@ -3,17 +3,17 @@ package com.appsmith.server.services.ce; import com.appsmith.external.constants.AnalyticsEvents; import com.appsmith.external.models.BaseDomain; import com.appsmith.server.configurations.CommonConfig; +import com.appsmith.server.configurations.ProjectProperties; import com.appsmith.server.constants.FieldName; import com.appsmith.server.domains.NewAction; import com.appsmith.server.domains.NewPage; import com.appsmith.server.domains.User; import com.appsmith.server.domains.UserData; import com.appsmith.server.helpers.ExchangeUtils; -import com.appsmith.server.helpers.PolicyUtils; import com.appsmith.server.helpers.UserUtils; +import com.appsmith.server.repositories.UserDataRepository; import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.SessionUserService; -import com.google.gson.Gson; import com.segment.analytics.Analytics; import com.segment.analytics.messages.IdentifyMessage; import com.segment.analytics.messages.TrackMessage; @@ -39,22 +39,25 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE { private final UserUtils userUtils; - private final Gson gson; + private final ProjectProperties projectProperties; + + private final UserDataRepository userDataRepository; @Autowired public AnalyticsServiceCEImpl(@Autowired(required = false) Analytics analytics, SessionUserService sessionUserService, CommonConfig commonConfig, ConfigService configService, - PolicyUtils policyUtils, UserUtils userUtils, - Gson gson) { + ProjectProperties projectProperties, + UserDataRepository userDataRepository) { this.analytics = analytics; this.sessionUserService = sessionUserService; this.commonConfig = commonConfig; this.configService = configService; this.userUtils = userUtils; - this.gson = gson; + this.projectProperties = projectProperties; + this.userDataRepository = userDataRepository; } public boolean isActive() { @@ -65,18 +68,34 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE { return value == null ? "" : DigestUtils.sha256Hex(value); } + @Override public Mono identifyUser(User user, UserData userData) { + return identifyUser(user, userData, null); + } + + @Override + public Mono identifyUser(User user, UserData userData, String recentlyUsedWorkspaceId) { if (!isActive()) { return Mono.just(user); } Mono isSuperUserMono = userUtils.isSuperUser(user); - return Mono.just(user) - .zipWith(isSuperUserMono) + final Mono recentlyUsedWorkspaceIdMono = StringUtils.isEmpty(recentlyUsedWorkspaceId) + ? userDataRepository.fetchMostRecentlyUsedWorkspaceId(user.getId()).defaultIfEmpty("") + : Mono.just(recentlyUsedWorkspaceId); + + return Mono.zip( + Mono.just(user), + isSuperUserMono, + configService.getInstanceId() + .defaultIfEmpty("unknown-instance-id"), + recentlyUsedWorkspaceIdMono + ) .map(tuple -> { - User savedUser = tuple.getT1(); - final Boolean isSuperUser = tuple.getT2(); + final User savedUser = tuple.getT1(); + final boolean isSuperUser = tuple.getT2(); + final String instanceId = tuple.getT3(); String username = savedUser.getUsername(); String name = savedUser.getName(); @@ -92,7 +111,9 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE { .traits(Map.of( "name", ObjectUtils.defaultIfNull(name, ""), "email", ObjectUtils.defaultIfNull(email, ""), - "isSuperUser", isSuperUser != null && isSuperUser, + "isSuperUser", isSuperUser, + "instanceId", instanceId, + "mostRecentlyUsedWorkspaceId", tuple.getT4(), "role", ObjectUtils.defaultIfNull(userData.getRole(), ""), "goal", ObjectUtils.defaultIfNull(userData.getUseCase(), "") )) @@ -174,6 +195,7 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE { TrackMessage.Builder messageBuilder = TrackMessage.builder(event).userId(userIdToSend); analyticsProperties.put("originService", "appsmith-server"); analyticsProperties.put("instanceId", instanceId); + analyticsProperties.put("version", projectProperties.getVersion()); messageBuilder = messageBuilder.properties(analyticsProperties); analytics.enqueue(messageBuilder); return instanceId; @@ -226,7 +248,7 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE { return Mono.just(object); } - final String username = (object instanceof User ? (User) object : user).getUsername(); + final String username = (object instanceof User objectAsUser ? objectAsUser : user).getUsername(); HashMap analyticsProperties = new HashMap<>(); analyticsProperties.put("id", id); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserDataServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserDataServiceCE.java index 70ca326f79..569fae12cd 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserDataServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserDataServiceCE.java @@ -50,5 +50,4 @@ public interface UserDataServiceCE { Mono setCommentState(CommentOnboardingState commentOnboardingState); Mono removeRecentWorkspaceAndApps(String userId, String workspaceId); - } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserDataServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserDataServiceCEImpl.java index 23253c7e60..6783a592fb 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserDataServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserDataServiceCEImpl.java @@ -22,6 +22,7 @@ import com.appsmith.server.solutions.ReleaseNotesService; import com.appsmith.server.solutions.UserChangedHandler; import com.mongodb.DBObject; import com.mongodb.client.result.UpdateResult; +import org.apache.commons.collections.map.Flat3Map; import org.apache.commons.lang3.ObjectUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; @@ -36,6 +37,8 @@ import reactor.core.publisher.Mono; import reactor.core.scheduler.Scheduler; import jakarta.validation.Validator; +import reactor.util.function.Tuple2; + import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -261,17 +264,25 @@ public class UserDataServiceCEImpl extends BaseService updateLastUsedAppAndWorkspaceList(Application application) { - return this.getForCurrentUser().flatMap(userData -> { - // set recently used workspace ids - userData.setRecentlyUsedWorkspaceIds( - addIdToRecentList(userData.getRecentlyUsedWorkspaceIds(), application.getWorkspaceId(), 10) - ); - // set recently used application ids - userData.setRecentlyUsedAppIds( - addIdToRecentList(userData.getRecentlyUsedAppIds(), application.getId(), 20) - ); - return repository.save(userData); - }); + return sessionUserService.getCurrentUser() + .zipWhen(this::getForUser) + .flatMap(tuple -> { + final User user = tuple.getT1(); + final UserData userData = tuple.getT2(); + // set recently used workspace ids + userData.setRecentlyUsedWorkspaceIds( + addIdToRecentList(userData.getRecentlyUsedWorkspaceIds(), application.getWorkspaceId(), 10) + ); + // set recently used application ids + userData.setRecentlyUsedAppIds( + addIdToRecentList(userData.getRecentlyUsedAppIds(), application.getId(), 20) + ); + return Mono.zip( + analyticsService.identifyUser(user, userData, application.getWorkspaceId()), + repository.save(userData) + ); + }) + .map(Tuple2::getT2); } @Override @@ -330,4 +341,5 @@ public class UserDataServiceCEImpl extends BaseService