Segment & Rollbar Integration

This commit is contained in:
Trisha Anand 2019-09-25 16:20:51 +00:00
parent 3a3521a539
commit 566a245451
30 changed files with 552 additions and 368 deletions

View File

@ -1,7 +1,6 @@
package com.appsmith.external.plugins; package com.appsmith.external.plugins;
import com.appsmith.external.models.ActionConfiguration; import com.appsmith.external.models.ActionConfiguration;
import com.appsmith.external.models.CommandParams;
import com.appsmith.external.models.Param; import com.appsmith.external.models.Param;
import com.appsmith.external.models.ResourceConfiguration; import com.appsmith.external.models.ResourceConfiguration;
import org.pf4j.ExtensionPoint; import org.pf4j.ExtensionPoint;

View File

@ -19,7 +19,7 @@
<plugin.class>com.external.plugins.PostgresPlugin</plugin.class> <plugin.class>com.external.plugins.PostgresPlugin</plugin.class>
<plugin.version>1.0-SNAPSHOT</plugin.version> <plugin.version>1.0-SNAPSHOT</plugin.version>
<plugin.provider>tech@appsmith.com</plugin.provider> <plugin.provider>tech@appsmith.com</plugin.provider>
<plugin.dependencies /> <plugin.dependencies/>
</properties> </properties>
<dependencies> <dependencies>

View File

@ -1,7 +1,6 @@
package com.external.plugins; package com.external.plugins;
import com.appsmith.external.models.ActionConfiguration; import com.appsmith.external.models.ActionConfiguration;
import com.appsmith.external.models.CommandParams;
import com.appsmith.external.models.Param; import com.appsmith.external.models.Param;
import com.appsmith.external.models.ResourceConfiguration; import com.appsmith.external.models.ResourceConfiguration;
import com.appsmith.external.plugins.BasePlugin; import com.appsmith.external.plugins.BasePlugin;
@ -13,7 +12,6 @@ import org.pf4j.PluginWrapper;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import javax.annotation.Resource;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.ResultSet; import java.sql.ResultSet;
@ -26,14 +24,14 @@ import java.util.List;
@Slf4j @Slf4j
public class PostgresPlugin extends BasePlugin { public class PostgresPlugin extends BasePlugin {
static String JDBC_DRIVER="org.postgresql.Driver"; static String JDBC_DRIVER = "org.postgresql.Driver";
static String DB_URL="jdbc:postgresql://localhost/mobtools"; static String DB_URL = "jdbc:postgresql://localhost/mobtools";
// Database credentials // Database credentials
static String DB_USER="root"; static String DB_USER = "root";
static String DB_PASS="root"; static String DB_PASS = "root";
static Connection conn = null; static Connection conn = null;
@ -61,7 +59,7 @@ public class PostgresPlugin extends BasePlugin {
public void stop() throws PluginException { public void stop() throws PluginException {
log.debug("PostgresPlugin.stop()"); log.debug("PostgresPlugin.stop()");
try { try {
if(conn != null) { if (conn != null) {
conn.close(); conn.close();
} }
} catch (SQLException e) { } catch (SQLException e) {

View File

@ -1,20 +1,18 @@
package com.external.plugins; package com.external.plugins;
import static org.junit.Assert.assertTrue;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.assertTrue;
/** /**
* Unit test for simple App. * Unit test for simple App.
*/ */
public class PostgresPluginTest public class PostgresPluginTest {
{
/** /**
* Rigorous Test :-) * Rigorous Test :-)
*/ */
@Test @Test
public void shouldAnswerWithTrue() public void shouldAnswerWithTrue() {
{ assertTrue(true);
assertTrue( true );
} }
} }

View File

@ -19,7 +19,7 @@
<plugin.class>com.external.plugins.RestApiPlugin</plugin.class> <plugin.class>com.external.plugins.RestApiPlugin</plugin.class>
<plugin.version>1.0-SNAPSHOT</plugin.version> <plugin.version>1.0-SNAPSHOT</plugin.version>
<plugin.provider>tech@appsmith.com</plugin.provider> <plugin.provider>tech@appsmith.com</plugin.provider>
<plugin.dependencies /> <plugin.dependencies/>
</properties> </properties>
<dependencies> <dependencies>

View File

@ -37,16 +37,17 @@ public class RestApiPlugin extends BasePlugin {
ActionConfiguration actionConfiguration, ActionConfiguration actionConfiguration,
List<Param> params) { List<Param> params) {
JSONObject requestBody = actionConfiguration.getBody(); JSONObject requestBody = actionConfiguration.getBody();
if(requestBody == null) { if (requestBody == null) {
requestBody = new JSONObject(); requestBody = new JSONObject();
} }
//TODO: Substitue variables from params in all parts (actionConfig, resourceConfig etc) via JsonPath: https://github.com/json-path/JsonPath
Map<String, Param> propertyMap = params.stream() Map<String, Param> propertyMap = params.stream()
.collect(Collectors.toMap(Param::getKey, param -> param)); .collect(Collectors.toMap(Param::getKey, param -> param));
String path = (actionConfiguration.getPath() == null) ? "" : actionConfiguration.getPath(); String path = (actionConfiguration.getPath() == null) ? "" : actionConfiguration.getPath();
String url = resourceConfiguration.getUrl() + path; String url = resourceConfiguration.getUrl() + path;
HttpMethod httpMethod = actionConfiguration.getHttpMethod(); HttpMethod httpMethod = actionConfiguration.getHttpMethod();
if(httpMethod == null) { if (httpMethod == null) {
return Flux.error(new Exception("HttpMethod must not be null")); return Flux.error(new Exception("HttpMethod must not be null"));
} }
@ -54,6 +55,7 @@ public class RestApiPlugin extends BasePlugin {
WebClient webClient = WebClient.builder() WebClient webClient = WebClient.builder()
.baseUrl(url) .baseUrl(url)
// TODO: Ideally this should come from action / resource config
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build(); .build();
@ -63,6 +65,7 @@ public class RestApiPlugin extends BasePlugin {
Mono<ClientResponse> responseMono = request.exchange(); Mono<ClientResponse> responseMono = request.exchange();
return responseMono.flatMapMany(response -> { return responseMono.flatMapMany(response -> {
log.debug("Got response: {}", response); log.debug("Got response: {}", response);
// TODO: Refactor for better switch case
List<String> contentTypes = response.headers().header(HttpHeaders.CONTENT_TYPE); List<String> contentTypes = response.headers().header(HttpHeaders.CONTENT_TYPE);
Class clazz = String.class; Class clazz = String.class;
if (contentTypes != null && contentTypes.size() > 0) { if (contentTypes != null && contentTypes.size() > 0) {

View File

@ -1,20 +1,18 @@
package com.external.plugins; package com.external.plugins;
import static org.junit.Assert.assertTrue;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.assertTrue;
/** /**
* Unit test for simple App. * Unit test for simple App.
*/ */
public class RestApiPluginTest public class RestApiPluginTest {
{
/** /**
* Rigorous Test :-) * Rigorous Test :-)
*/ */
@Test @Test
public void shouldAnswerWithTrue() public void shouldAnswerWithTrue() {
{ assertTrue(true);
assertTrue( true );
} }
} }

View File

@ -101,7 +101,16 @@
<artifactId>de.flapdoodle.embed.mongo</artifactId> <artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.segment.analytics.java</groupId>
<artifactId>analytics</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency>
<!-- Plugin dependencies --> <!-- Plugin dependencies -->
<dependency> <dependency>
<groupId>org.pf4j</groupId> <groupId>org.pf4j</groupId>
@ -132,6 +141,17 @@
<version>3.2.11.RELEASE</version> <version>3.2.11.RELEASE</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.segment.analytics.java</groupId>
<artifactId>analytics</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.rollbar</groupId>
<artifactId>rollbar-java</artifactId>
<version>1.5.2</version>
</dependency>
</dependencies> </dependencies>

View File

@ -0,0 +1,20 @@
package com.appsmith.server.configurations;
import com.rollbar.notifier.Rollbar;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static com.rollbar.notifier.config.ConfigBuilder.withAccessToken;
@Configuration
public class RollbarConfig {
@Value("${com.rollbar.access-token}")
String rollbarAccessToken;
@Bean
Rollbar rollbarConfiguration() {
return Rollbar.init(withAccessToken(rollbarAccessToken).build());
}
}

View File

@ -0,0 +1,17 @@
package com.appsmith.server.configurations;
import com.segment.analytics.Analytics;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SegmentConfig {
@Value("${segment.writeKey}")
private String writeKey;
@Bean
public Analytics analyticsRunner() {
return Analytics.builder(writeKey).build();
}
}

View File

@ -1,7 +1,7 @@
package com.appsmith.server.controllers; package com.appsmith.server.controllers;
import com.appsmith.server.domains.User; import com.appsmith.server.domains.User;
import com.appsmith.server.services.UserService; import com.appsmith.server.services.SessionUserService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -16,10 +16,10 @@ import java.security.Principal;
@RequestMapping("") @RequestMapping("")
public class IndexController { public class IndexController {
private final UserService service; private final SessionUserService service;
@Autowired @Autowired
public IndexController(UserService service) { public IndexController(SessionUserService service) {
this.service = service; this.service = service;
} }

View File

@ -18,5 +18,4 @@ public class PropertyPane extends BaseDomain {
Map<String, List<WidgetSectionProperty>> config; Map<String, List<WidgetSectionProperty>> config;
String configVersion;
} }

View File

@ -1,7 +1,10 @@
package com.appsmith.server.exceptions; package com.appsmith.server.exceptions;
import com.appsmith.server.dtos.ResponseDTO; import com.appsmith.server.dtos.ResponseDTO;
import com.rollbar.notifier.Rollbar;
import com.segment.analytics.Analytics;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
@ -16,6 +19,14 @@ import reactor.core.publisher.Mono;
@ControllerAdvice @ControllerAdvice
@Slf4j @Slf4j
public class GlobalExceptionHandler { public class GlobalExceptionHandler {
private final Analytics analytics;
private final Rollbar rollbar;
@Autowired
public GlobalExceptionHandler(Analytics analytics, Rollbar rollbar) {
this.analytics = analytics;
this.rollbar = rollbar;
}
/** /**
* This function only catches the AppsmithException type and formats it into ResponseEntity<ErrorDTO> object * This function only catches the AppsmithException type and formats it into ResponseEntity<ErrorDTO> object
@ -31,6 +42,7 @@ public class GlobalExceptionHandler {
public Mono<ResponseDTO<ErrorDTO>> catchAppsmithException(AppsmithException e, ServerWebExchange exchange) { public Mono<ResponseDTO<ErrorDTO>> catchAppsmithException(AppsmithException e, ServerWebExchange exchange) {
exchange.getResponse().setStatusCode(HttpStatus.resolve(e.getHttpStatus())); exchange.getResponse().setStatusCode(HttpStatus.resolve(e.getHttpStatus()));
log.error("", e); log.error("", e);
rollbar.log(e);
return Mono.just(new ResponseDTO<>(e.getHttpStatus(), new ErrorDTO(e.getAppErrorCode(), e.getMessage()))); return Mono.just(new ResponseDTO<>(e.getHttpStatus(), new ErrorDTO(e.getAppErrorCode(), e.getMessage())));
} }
@ -47,6 +59,7 @@ public class GlobalExceptionHandler {
public Mono<ResponseDTO<ErrorDTO>> catchException(Exception e, ServerWebExchange exchange) { public Mono<ResponseDTO<ErrorDTO>> catchException(Exception e, ServerWebExchange exchange) {
exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
log.error("", e); log.error("", e);
rollbar.log(e);
return Mono.just(new ResponseDTO<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), new ErrorDTO(AppsmithError.INTERNAL_SERVER_ERROR.getHttpErrorCode(), return Mono.just(new ResponseDTO<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), new ErrorDTO(AppsmithError.INTERNAL_SERVER_ERROR.getHttpErrorCode(),
AppsmithError.INTERNAL_SERVER_ERROR.getMessage()))); AppsmithError.INTERNAL_SERVER_ERROR.getMessage())));
} }

View File

@ -6,10 +6,12 @@ import com.appsmith.server.domains.Page;
import com.appsmith.server.domains.PageAction; import com.appsmith.server.domains.PageAction;
import com.appsmith.server.domains.Plugin; import com.appsmith.server.domains.Plugin;
import com.appsmith.server.domains.Resource; import com.appsmith.server.domains.Resource;
import com.appsmith.server.domains.User;
import com.appsmith.server.dtos.ExecuteActionDTO; import com.appsmith.server.dtos.ExecuteActionDTO;
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.repositories.ActionRepository; import com.appsmith.server.repositories.ActionRepository;
import com.segment.analytics.Analytics;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.pf4j.PluginManager; import org.pf4j.PluginManager;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -44,8 +46,10 @@ public class ActionServiceImpl extends BaseService<ActionRepository, Action, Str
ResourceService resourceService, ResourceService resourceService,
PluginService pluginService, PluginService pluginService,
PageService pageService, PageService pageService,
PluginManager pluginManager) { PluginManager pluginManager,
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository); Analytics analytics,
SessionUserService sessionUserService) {
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analytics, sessionUserService);
this.repository = repository; this.repository = repository;
this.resourceService = resourceService; this.resourceService = resourceService;
this.pluginService = pluginService; this.pluginService = pluginService;
@ -63,6 +67,7 @@ public class ActionServiceImpl extends BaseService<ActionRepository, Action, Str
return Mono.error(new AppsmithException(AppsmithError.PAGE_ID_NOT_GIVEN)); return Mono.error(new AppsmithException(AppsmithError.PAGE_ID_NOT_GIVEN));
} }
Mono<User> userMono = super.sessionUserService.getCurrentUser();
Mono<Resource> resourceMono = resourceService.findById(action.getResourceId()); Mono<Resource> resourceMono = resourceService.findById(action.getResourceId());
Mono<Plugin> pluginMono = resourceMono.flatMap(resource -> pluginService.findById(resource.getPluginId())); Mono<Plugin> pluginMono = resourceMono.flatMap(resource -> pluginService.findById(resource.getPluginId()));
Mono<Page> pageMono = pageService.findById(action.getPageId()); Mono<Page> pageMono = pageService.findById(action.getPageId());
@ -96,7 +101,9 @@ public class ActionServiceImpl extends BaseService<ActionRepository, Action, Str
return page; return page;
}) })
.flatMap(pageService::save) .flatMap(pageService::save)
.then(Mono.just(action1)); .then(Mono.just(action1))
//Now publish this event
.flatMap(this::segmentTrackCreate);
}); });
} }
@ -129,7 +136,7 @@ public class ActionServiceImpl extends BaseService<ActionRepository, Action, Str
return actionMono.flatMap(action -> resourceMono.zipWith(pluginExecutorMono, (resource, pluginExecutor) -> return actionMono.flatMap(action -> resourceMono.zipWith(pluginExecutorMono, (resource, pluginExecutor) ->
{ {
log.debug("*** About to invoke the plugin**"); log.debug("*** About to invoke the plugin**");
// TODO: The CommandParams is being passed as null here. Move it to interfaces.CommandParams // TODO: The CommandParams is being passed as null here. Move it to interfaces.CommandParams - N/A
return pluginExecutor.execute(resource.getResourceConfiguration(), action.getActionConfiguration(), executeActionDTO.getParams()); return pluginExecutor.execute(resource.getResourceConfiguration(), action.getActionConfiguration(), executeActionDTO.getParams());
})) }))
.flatMapIterable(Flux::toIterable); .flatMapIterable(Flux::toIterable);

View File

@ -6,6 +6,7 @@ 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;
import com.appsmith.server.repositories.ApplicationRepository; import com.appsmith.server.repositories.ApplicationRepository;
import com.segment.analytics.Analytics;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
@ -22,12 +23,12 @@ import javax.validation.Validator;
@Service @Service
public class ApplicationServiceImpl extends BaseService<ApplicationRepository, Application, String> implements ApplicationService { public class ApplicationServiceImpl extends BaseService<ApplicationRepository, Application, String> implements ApplicationService {
private final UserService userService; private final Analytics analytics;
@Autowired @Autowired
public ApplicationServiceImpl(Scheduler scheduler, Validator validator, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, ApplicationRepository repository, UserService userService) { public ApplicationServiceImpl(Scheduler scheduler, Validator validator, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, ApplicationRepository repository, SessionUserService sessionUserService, Analytics analytics) {
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository); super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analytics, sessionUserService);
this.userService = userService; this.analytics = analytics;
} }
@Override @Override
@ -36,7 +37,7 @@ public class ApplicationServiceImpl extends BaseService<ApplicationRepository, A
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.NAME)); return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.NAME));
} }
Mono<User> userMono = userService.getCurrentUser(); Mono<User> userMono = super.sessionUserService.getCurrentUser();
return userMono return userMono
.map(user -> user.getOrganizationId()) .map(user -> user.getOrganizationId())
@ -44,12 +45,14 @@ public class ApplicationServiceImpl extends BaseService<ApplicationRepository, A
application.setOrganizationId(orgId); application.setOrganizationId(orgId);
return application; return application;
}) })
.flatMap(repository::save); .flatMap(repository::save)
//Log the event to Segment
.flatMap(this::segmentTrackCreate);
} }
@Override @Override
public Flux<Application> get() { public Flux<Application> get() {
Mono<User> userMono = userService.getCurrentUser(); Mono<User> userMono = super.sessionUserService.getCurrentUser();
return userMono return userMono
.map(user -> user.getOrganizationId()) .map(user -> user.getOrganizationId())
@ -62,7 +65,7 @@ public class ApplicationServiceImpl extends BaseService<ApplicationRepository, A
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ID)); return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ID));
} }
Mono<User> userMono = userService.getCurrentUser(); Mono<User> userMono = super.sessionUserService.getCurrentUser();
return userMono return userMono
.map(user -> user.getOrganizationId()) .map(user -> user.getOrganizationId())

View File

@ -2,11 +2,14 @@ package com.appsmith.server.services;
import com.appsmith.server.constants.FieldName; import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.BaseDomain; import com.appsmith.server.domains.BaseDomain;
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;
import com.appsmith.server.repositories.BaseRepository; import com.appsmith.server.repositories.BaseRepository;
import com.mongodb.BasicDBObject; import com.mongodb.BasicDBObject;
import com.mongodb.DBObject; import com.mongodb.DBObject;
import com.segment.analytics.Analytics;
import com.segment.analytics.messages.TrackMessage;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Criteria;
@ -17,6 +20,7 @@ import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler; import reactor.core.scheduler.Scheduler;
import javax.validation.Validator; import javax.validation.Validator;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
public abstract class BaseService<R extends BaseRepository, T extends BaseDomain, ID> implements CrudService<T, ID> { public abstract class BaseService<R extends BaseRepository, T extends BaseDomain, ID> implements CrudService<T, ID> {
@ -31,16 +35,22 @@ public abstract class BaseService<R extends BaseRepository, T extends BaseDomain
protected final Validator validator; protected final Validator validator;
protected final Analytics analytics;
protected final SessionUserService sessionUserService;
public BaseService(Scheduler scheduler, public BaseService(Scheduler scheduler,
Validator validator, Validator validator,
MongoConverter mongoConverter, MongoConverter mongoConverter,
ReactiveMongoTemplate reactiveMongoTemplate, ReactiveMongoTemplate reactiveMongoTemplate,
R repository) { R repository, Analytics analytics, SessionUserService sessionUserService) {
this.scheduler = scheduler; this.scheduler = scheduler;
this.validator = validator; this.validator = validator;
this.mongoConverter = mongoConverter; this.mongoConverter = mongoConverter;
this.mongoTemplate = reactiveMongoTemplate; this.mongoTemplate = reactiveMongoTemplate;
this.repository = repository; this.repository = repository;
this.analytics = analytics;
this.sessionUserService = sessionUserService;
} }
@Override @Override
@ -78,9 +88,11 @@ public abstract class BaseService<R extends BaseRepository, T extends BaseDomain
@Override @Override
public Mono<T> create(T object) { public Mono<T> create(T object) {
Mono<User> userMono = sessionUserService.getCurrentUser();
return Mono.just(object) return Mono.just(object)
.flatMap(this::validateObject) .flatMap(this::validateObject)
.flatMap(repository::save); .flatMap(repository::save)
.flatMap(this::segmentTrackCreate);
} }
private DBObject getDbObject(Object o) { private DBObject getDbObject(Object o) {
@ -106,4 +118,21 @@ public abstract class BaseService<R extends BaseRepository, T extends BaseDomain
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, constraint.stream().findFirst().get().getPropertyPath())); return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, constraint.stream().findFirst().get().getPropertyPath()));
}); });
} }
protected Mono<T> segmentTrackCreate(Object savedObject) {
Mono<User> userMono = sessionUserService.getCurrentUser();
return userMono
.map(user -> {
HashMap<String, String> analyticsProperties = new HashMap<>();
analyticsProperties.put("id", ((BaseDomain) savedObject).getId());
analyticsProperties.put("organizationId", user.getOrganizationId());
analytics.enqueue(
TrackMessage.builder("MONGO_DB_CREATE_" + savedObject.getClass())
.userId(user.getId())
.properties(analyticsProperties)
);
return (T) savedObject;
})
.switchIfEmpty(Mono.just((T) savedObject));
}
} }

View File

@ -4,9 +4,11 @@ import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.Organization;
import com.appsmith.server.domains.OrganizationSetting; import com.appsmith.server.domains.OrganizationSetting;
import com.appsmith.server.domains.Setting; import com.appsmith.server.domains.Setting;
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;
import com.appsmith.server.repositories.OrganizationRepository; import com.appsmith.server.repositories.OrganizationRepository;
import com.segment.analytics.Analytics;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
@ -33,8 +35,10 @@ public class OrganizationServiceImpl extends BaseService<OrganizationRepository,
MongoConverter mongoConverter, MongoConverter mongoConverter,
ReactiveMongoTemplate reactiveMongoTemplate, ReactiveMongoTemplate reactiveMongoTemplate,
OrganizationRepository repository, OrganizationRepository repository,
SettingService settingService) { SettingService settingService,
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository); Analytics analytics,
SessionUserService sessionUserService) {
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analytics, sessionUserService);
this.repository = repository; this.repository = repository;
this.settingService = settingService; this.settingService = settingService;
} }
@ -55,13 +59,13 @@ public class OrganizationServiceImpl extends BaseService<OrganizationRepository,
if (organization == null) { if (organization == null) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ORGANIZATION)); return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ORGANIZATION));
} }
return Mono.just(organization) return Mono.just(organization)
.flatMap(this::validateObject) .flatMap(this::validateObject)
//transform the organization data to embed setting object in each object in organizationSetting list. //transform the organization data to embed setting object in each object in organizationSetting list.
.flatMap(this::enhanceOrganizationSettingList) .flatMap(this::enhanceOrganizationSettingList)
//Call the library function to save the updated organization //Call the library function to save the updated organization
.flatMap(repository::save); .flatMap(repository::save)
.flatMap(this::segmentTrackCreate);
} }
private Mono<Organization> enhanceOrganizationSettingList(Organization organization) { private Mono<Organization> enhanceOrganizationSettingList(Organization organization) {

View File

@ -7,6 +7,7 @@ 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;
import com.appsmith.server.repositories.PageRepository; import com.appsmith.server.repositories.PageRepository;
import com.segment.analytics.Analytics;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -24,13 +25,12 @@ import java.util.List;
@Slf4j @Slf4j
public class PageServiceImpl extends BaseService<PageRepository, Page, String> implements PageService { public class PageServiceImpl extends BaseService<PageRepository, Page, String> implements PageService {
private final UserService userService;
private final ApplicationService applicationService; private final ApplicationService applicationService;
@Autowired @Autowired
public PageServiceImpl(Scheduler scheduler, Validator validator, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, PageRepository repository, UserService userService, ApplicationService applicationService) { public PageServiceImpl(Scheduler scheduler, Validator validator, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, PageRepository repository, ApplicationService applicationService,
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository); Analytics analytics, SessionUserService sessionUserService) {
this.userService = userService; super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analytics, sessionUserService);
this.applicationService = applicationService; this.applicationService = applicationService;
} }
@ -43,6 +43,9 @@ public class PageServiceImpl extends BaseService<PageRepository, Page, String> i
} else if (page.getApplicationId() == null) { } else if (page.getApplicationId() == null) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.APPLICATIONID)); return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.APPLICATIONID));
} }
Mono<User> userMono = super.sessionUserService.getCurrentUser();
List<Layout> layoutList = page.getLayouts(); List<Layout> layoutList = page.getLayouts();
if (layoutList == null) { if (layoutList == null) {
layoutList = new ArrayList<>(); layoutList = new ArrayList<>();
@ -51,7 +54,9 @@ public class PageServiceImpl extends BaseService<PageRepository, Page, String> i
layoutList.add(createDefaultLayout()); layoutList.add(createDefaultLayout());
page.setLayouts(layoutList); page.setLayouts(layoutList);
} }
return repository.save(page); return repository
.save(page)
.flatMap(this::segmentTrackCreate);
} }
@ -72,7 +77,7 @@ public class PageServiceImpl extends BaseService<PageRepository, Page, String> i
@Override @Override
public Mono<Page> doesPageIdBelongToCurrentUserOrganization(Page page) { public Mono<Page> doesPageIdBelongToCurrentUserOrganization(Page page) {
Mono<User> userMono = userService.getCurrentUser(); Mono<User> userMono = super.sessionUserService.getCurrentUser();
final String[] username = {null}; final String[] username = {null};
return userMono return userMono

View File

@ -10,6 +10,7 @@ import com.appsmith.server.dtos.PluginOrgDTO;
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.repositories.PluginRepository; import com.appsmith.server.repositories.PluginRepository;
import com.segment.analytics.Analytics;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
@ -30,7 +31,6 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
private final PluginRepository pluginRepository; private final PluginRepository pluginRepository;
private final ApplicationContext applicationContext; private final ApplicationContext applicationContext;
private final OrganizationService organizationService; private final OrganizationService organizationService;
private final UserService userService;
@Autowired @Autowired
public PluginServiceImpl(Scheduler scheduler, public PluginServiceImpl(Scheduler scheduler,
@ -39,12 +39,13 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
ReactiveMongoTemplate reactiveMongoTemplate, ReactiveMongoTemplate reactiveMongoTemplate,
PluginRepository repository, PluginRepository repository,
ApplicationContext applicationContext, ApplicationContext applicationContext,
OrganizationService organizationService, UserService userService) { OrganizationService organizationService,
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository); Analytics analytics,
SessionUserService sessionUserService) {
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analytics, sessionUserService);
this.applicationContext = applicationContext; this.applicationContext = applicationContext;
pluginRepository = repository; pluginRepository = repository;
this.organizationService = organizationService; this.organizationService = organizationService;
this.userService = userService;
} }
public OldPluginExecutor getPluginExecutor(PluginType pluginType, String className) { public OldPluginExecutor getPluginExecutor(PluginType pluginType, String className) {
@ -64,8 +65,12 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, "id")); return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, "id"));
} }
Mono<User> userMono = super.sessionUserService.getCurrentUser();
plugin.setDeleted(false); plugin.setDeleted(false);
return pluginRepository.save(plugin); return pluginRepository
.save(plugin)
.flatMap(this::segmentTrackCreate);
} }
@Override @Override
@ -86,7 +91,7 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
} }
//Find the organization using id and plugin id -> This is to find if the organization has the plugin installed //Find the organization using id and plugin id -> This is to find if the organization has the plugin installed
Mono<User> userMono = userService.getCurrentUser(); Mono<User> userMono = super.sessionUserService.getCurrentUser();
Mono<Organization> organizationMono = userMono.flatMap(user -> Mono<Organization> organizationMono = userMono.flatMap(user ->
organizationService.findByIdAndPluginsPluginId(user.getOrganizationId(), pluginDTO.getPluginId())); organizationService.findByIdAndPluginsPluginId(user.getOrganizationId(), pluginDTO.getPluginId()));
@ -107,7 +112,7 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
private Mono<Organization> storeOrganizationPlugin(PluginOrgDTO pluginDTO, OrganizationPluginStatus status) { private Mono<Organization> storeOrganizationPlugin(PluginOrgDTO pluginDTO, OrganizationPluginStatus status) {
//Find the organization using id and plugin id -> This is to find if the organization already has the plugin installed //Find the organization using id and plugin id -> This is to find if the organization already has the plugin installed
Mono<User> userMono = userService.getCurrentUser(); Mono<User> userMono = super.sessionUserService.getCurrentUser();
Mono<Organization> organizationMono = userMono.flatMap(user -> Mono<Organization> organizationMono = userMono.flatMap(user ->
organizationService.findByIdAndPluginsPluginId(user.getOrganizationId(), pluginDTO.getPluginId())); organizationService.findByIdAndPluginsPluginId(user.getOrganizationId(), pluginDTO.getPluginId()));

View File

@ -6,6 +6,7 @@ import com.appsmith.server.domains.WidgetSectionProperty;
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.repositories.PropertyPaneRepository; import com.appsmith.server.repositories.PropertyPaneRepository;
import com.segment.analytics.Analytics;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
@ -15,19 +16,18 @@ import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler; import reactor.core.scheduler.Scheduler;
import javax.validation.Validator; import javax.validation.Validator;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@Slf4j @Slf4j
@Service @Service
public class PropertyPaneServiceImpl extends BaseService<PropertyPaneRepository, PropertyPane, String> implements PropertyPaneService { public class PropertyPaneServiceImpl extends BaseService<PropertyPaneRepository, PropertyPane, String> implements PropertyPaneService {
public PropertyPaneServiceImpl(Scheduler scheduler, Validator validator, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, PropertyPaneRepository repository) { public PropertyPaneServiceImpl(Scheduler scheduler, Validator validator, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, PropertyPaneRepository repository, Analytics analytics, SessionUserService sessionUserService) {
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository); super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analytics, sessionUserService);
} }
@Override @Override
public Mono<PropertyPane> create (PropertyPane propertyPane) { public Mono<PropertyPane> create(PropertyPane propertyPane) {
if (propertyPane.getId() != null) { if (propertyPane.getId() != null) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, "id")); return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, "id"));
} }
@ -49,9 +49,6 @@ public class PropertyPaneServiceImpl extends BaseService<PropertyPaneRepository,
} }
return repository return repository
.save(propertyPane) .save(propertyPane)
.flatMap(savedPropertyPane -> { .flatMap(this::segmentTrackCreate);
savedPropertyPane.setConfigVersion(savedPropertyPane.getId());
return repository.save(savedPropertyPane);
});
} }
} }

View File

@ -6,6 +6,7 @@ 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;
import com.appsmith.server.repositories.ResourceRepository; import com.appsmith.server.repositories.ResourceRepository;
import com.segment.analytics.Analytics;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
@ -23,14 +24,13 @@ public class ResourceServiceImpl extends BaseService<ResourceRepository, Resourc
private final ResourceRepository repository; private final ResourceRepository repository;
private final OrganizationService organizationService; private final OrganizationService organizationService;
private final UserService userService;
@Autowired @Autowired
public ResourceServiceImpl(Scheduler scheduler, Validator validator, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, ResourceRepository repository, OrganizationService organizationService, PluginService pluginService, UserService userService) { public ResourceServiceImpl(Scheduler scheduler, Validator validator, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, ResourceRepository repository, OrganizationService organizationService, PluginService pluginService, Analytics analytics,
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository); SessionUserService sessionUserService) {
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analytics, sessionUserService);
this.repository = repository; this.repository = repository;
this.organizationService = organizationService; this.organizationService = organizationService;
this.userService = userService;
} }
@Override @Override
@ -41,7 +41,7 @@ public class ResourceServiceImpl extends BaseService<ResourceRepository, Resourc
return Mono.error(new AppsmithException(AppsmithError.PLUGIN_ID_NOT_GIVEN)); return Mono.error(new AppsmithException(AppsmithError.PLUGIN_ID_NOT_GIVEN));
} }
Mono<User> userMono = userService.getCurrentUser(); Mono<User> userMono = super.sessionUserService.getCurrentUser();
Mono<Organization> organizationMono = userMono.flatMap(user -> organizationService.findByIdAndPluginsPluginId(user.getOrganizationId(), resource.getPluginId())); Mono<Organization> organizationMono = userMono.flatMap(user -> organizationService.findByIdAndPluginsPluginId(user.getOrganizationId(), resource.getPluginId()));
@ -55,7 +55,8 @@ public class ResourceServiceImpl extends BaseService<ResourceRepository, Resourc
return organizationMono return organizationMono
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.PLUGIN_NOT_INSTALLED, resource.getPluginId()))) .switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.PLUGIN_NOT_INSTALLED, resource.getPluginId())))
.then(updatedResourceMono) .then(updatedResourceMono)
.flatMap(repository::save); .flatMap(repository::save)
.flatMap(this::segmentTrackCreate);
} }
@Override @Override

View File

@ -0,0 +1,8 @@
package com.appsmith.server.services;
import com.appsmith.server.domains.User;
import reactor.core.publisher.Mono;
public interface SessionUserService {
public Mono<User> getCurrentUser();
}

View File

@ -0,0 +1,41 @@
package com.appsmith.server.services;
import com.appsmith.server.domains.User;
import com.appsmith.server.repositories.UserRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
@Slf4j
@Service
public class SessionUserServiceImpl implements SessionUserService {
private final UserRepository repository;
public SessionUserServiceImpl(UserRepository userRepository) {
this.repository = userRepository;
}
@Override
public Mono<User> getCurrentUser() {
return ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
.map(Authentication::getPrincipal)
.flatMap(principal -> {
String email;
if (principal instanceof org.springframework.security.core.userdetails.User) {
org.springframework.security.core.userdetails.User user = (org.springframework.security.core.userdetails.User) principal;
//Assumption that the user has inputted an email as username during user creation and not english passport name
email = user.getUsername();
} else {
DefaultOidcUser defaultOidcUser = (DefaultOidcUser) principal;
email = defaultOidcUser.getEmail();
}
return repository.findByEmail(email);
});
}
}

View File

@ -2,6 +2,7 @@ package com.appsmith.server.services;
import com.appsmith.server.domains.Setting; import com.appsmith.server.domains.Setting;
import com.appsmith.server.repositories.SettingRepository; import com.appsmith.server.repositories.SettingRepository;
import com.segment.analytics.Analytics;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter;
@ -21,8 +22,10 @@ public class SettingServiceImpl extends BaseService<SettingRepository, Setting,
Validator validator, Validator validator,
MongoConverter mongoConverter, MongoConverter mongoConverter,
ReactiveMongoTemplate reactiveMongoTemplate, ReactiveMongoTemplate reactiveMongoTemplate,
SettingRepository repository) { SettingRepository repository,
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository); Analytics analytics,
SessionUserService sessionUserService) {
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analytics, sessionUserService);
this.repository = repository; this.repository = repository;
} }

View File

@ -11,5 +11,4 @@ public interface UserService extends CrudService<User, String> {
Mono<User> save(User newUser); Mono<User> save(User newUser);
Mono<User> getCurrentUser();
} }

View File

@ -5,22 +5,22 @@ import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.helpers.BeanCopyUtils; import com.appsmith.server.helpers.BeanCopyUtils;
import com.appsmith.server.repositories.UserRepository; import com.appsmith.server.repositories.UserRepository;
import com.segment.analytics.Analytics;
import com.segment.analytics.messages.IdentifyMessage;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler; import reactor.core.scheduler.Scheduler;
import javax.validation.Validator; import javax.validation.Validator;
import java.util.HashMap;
import java.util.Map;
@Slf4j @Slf4j
@Service @Service
@ -28,16 +28,21 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
private UserRepository repository; private UserRepository repository;
private final OrganizationService organizationService; private final OrganizationService organizationService;
private final Analytics analytics;
@Autowired @Autowired
public UserServiceImpl(Scheduler scheduler, public UserServiceImpl(Scheduler scheduler,
Validator validator, Validator validator,
MongoConverter mongoConverter, MongoConverter mongoConverter,
ReactiveMongoTemplate reactiveMongoTemplate, ReactiveMongoTemplate reactiveMongoTemplate,
UserRepository repository, OrganizationService organizationService) { UserRepository repository,
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository); OrganizationService organizationService,
Analytics analytics,
SessionUserService sessionUserService) {
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analytics, sessionUserService);
this.repository = repository; this.repository = repository;
this.organizationService = organizationService; this.organizationService = organizationService;
this.analytics = analytics;
} }
@Override @Override
@ -52,7 +57,20 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
@Override @Override
public Mono<User> save(User user) { public Mono<User> save(User user) {
return repository.save(user);
Mono<User> savedUserMono = repository.save(user);
return savedUserMono
.map(savedUser -> {
Map<String, String> traitsMap = new HashMap<>();
traitsMap.put("name", savedUser.getName());
traitsMap.put("email", savedUser.getEmail());
analytics.enqueue(IdentifyMessage.builder()
.userId(savedUser.getId())
.traits(traitsMap)
);
analytics.flush();
return savedUser;
});
} }
@Override @Override
@ -60,25 +78,6 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
return repository.findByName(username).block(); return repository.findByName(username).block();
} }
@Override
public Mono<User> getCurrentUser() {
return ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
.map(Authentication::getPrincipal)
.flatMap(principal -> {
String email;
if (principal instanceof org.springframework.security.core.userdetails.User) {
org.springframework.security.core.userdetails.User user = (org.springframework.security.core.userdetails.User) principal;
//Assumption that the user has inputted an email as username during user creation and not english passport name
email = user.getUsername();
} else {
DefaultOidcUser defaultOidcUser = (DefaultOidcUser) principal;
email = defaultOidcUser.getEmail();
}
return repository.findByEmail(email);
});
}
@Override @Override
public Mono<User> update(String id, User userUpdate) { public Mono<User> update(String id, User userUpdate) {
Mono<User> userFromRepository = repository.findById(id); Mono<User> userFromRepository = repository.findById(id);

View File

@ -2,6 +2,7 @@ package com.appsmith.server.services;
import com.appsmith.server.domains.Widget; import com.appsmith.server.domains.Widget;
import com.appsmith.server.repositories.WidgetRepository; import com.appsmith.server.repositories.WidgetRepository;
import com.segment.analytics.Analytics;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
@ -23,8 +24,10 @@ public class WidgetServiceImpl extends BaseService<WidgetRepository, Widget, Str
Validator validator, Validator validator,
MongoConverter mongoConverter, MongoConverter mongoConverter,
ReactiveMongoTemplate mongoTemplate, ReactiveMongoTemplate mongoTemplate,
WidgetRepository widgetRepository) { WidgetRepository widgetRepository,
super(scheduler, validator, mongoConverter, mongoTemplate, widgetRepository); Analytics analytics,
SessionUserService sessionUserService) {
super(scheduler, validator, mongoConverter, mongoTemplate, widgetRepository, analytics, sessionUserService);
this.widgetRepository = widgetRepository; this.widgetRepository = widgetRepository;
} }

View File

@ -4,12 +4,14 @@ spring.datasource.username=postgres
spring.datasource.password=root spring.datasource.password=root
spring.datasource.hikari.pool-name=Hikari-Eval-Pool spring.datasource.hikari.pool-name=Hikari-Eval-Pool
spring.datasource.hikari.maximum-pool-size=16 spring.datasource.hikari.maximum-pool-size=16
# JPA Properties # JPA Properties
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false
spring.jpa.show-sql=true spring.jpa.show-sql=true
# Jackson Properties # Jackson Properties
spring.jackson.default-property-inclusion=non_null spring.jackson.default-property-inclusion=non_null
# Segment Properties
segment.writeKey=FIRLqUgMYuTlyS6yqOE2hBGZs5umkWhr
com.rollbar.access-token=b91c4d5b9cac444088f4db9216ed6f42
com.rollbar.environment=development

View File

@ -0,0 +1,4 @@
dsn=https://5c388a93407a45a5886a941842e28d29@sentry.io/1758051
release=0.0.1
environment=local
stacktrace.hidecommon=false

View File

@ -9,6 +9,7 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@ -37,6 +38,7 @@ public class OrganizationServiceTest {
/* Tests for the Create Organization Flow */ /* Tests for the Create Organization Flow */
@Test @Test
@WithMockUser(username = "api_user")
public void nullCreateOrganization() { public void nullCreateOrganization() {
Mono<Organization> organizationResponse = organizationService.create(null); Mono<Organization> organizationResponse = organizationService.create(null);
StepVerifier.create(organizationResponse) StepVerifier.create(organizationResponse)
@ -46,6 +48,7 @@ public class OrganizationServiceTest {
} }
@Test @Test
@WithMockUser(username = "api_user")
public void nullName() { public void nullName() {
organization.setName(null); organization.setName(null);
Mono<Organization> organizationResponse = organizationService.create(organization); Mono<Organization> organizationResponse = organizationService.create(organization);
@ -56,8 +59,10 @@ public class OrganizationServiceTest {
} }
@Test @Test
@WithMockUser(username = "api_user")
public void validCreateOrganizationTest() { public void validCreateOrganizationTest() {
Mono<Organization> organizationResponse = organizationService.create(organization); Mono<Organization> organizationResponse = organizationService.create(organization)
.switchIfEmpty(Mono.error(new Exception("create is returning empty!!")));
StepVerifier.create(organizationResponse) StepVerifier.create(organizationResponse)
.assertNext(organization1 -> { .assertNext(organization1 -> {
assertThat(organization1.getName()).isEqualTo("Test Name"); assertThat(organization1.getName()).isEqualTo("Test Name");
@ -68,6 +73,7 @@ public class OrganizationServiceTest {
/* Tests for Get Organization Flow */ /* Tests for Get Organization Flow */
@Test @Test
@WithMockUser(username = "api_user")
public void getOrganizationInvalidId() { public void getOrganizationInvalidId() {
Mono<Organization> organizationMono = organizationService.getById("random-id"); Mono<Organization> organizationMono = organizationService.getById("random-id");
StepVerifier.create(organizationMono) StepVerifier.create(organizationMono)
@ -77,6 +83,7 @@ public class OrganizationServiceTest {
} }
@Test @Test
@WithMockUser(username = "api_user")
public void getOrganizationNullId() { public void getOrganizationNullId() {
Mono<Organization> organizationMono = organizationService.getById(null); Mono<Organization> organizationMono = organizationService.getById(null);
StepVerifier.create(organizationMono) StepVerifier.create(organizationMono)
@ -86,6 +93,7 @@ public class OrganizationServiceTest {
} }
@Test @Test
@WithMockUser(username = "api_user")
public void validGetOrganizationByName() { public void validGetOrganizationByName() {
Mono<Organization> createOrganization = organizationService.create(organization); Mono<Organization> createOrganization = organizationService.create(organization);
Mono<Organization> getOrganization = createOrganization.flatMap(t -> organizationService.getById(t.getId())); Mono<Organization> getOrganization = createOrganization.flatMap(t -> organizationService.getById(t.getId()));
@ -100,6 +108,7 @@ public class OrganizationServiceTest {
/* Tests for Update Organization Flow */ /* Tests for Update Organization Flow */
@Test @Test
@WithMockUser(username = "api_user")
public void validUpdateOrganization() { public void validUpdateOrganization() {
Organization organization = new Organization(); Organization organization = new Organization();
organization.setName("Test Name"); organization.setName("Test Name");