Removed DBRef from action. Added DBRef of plugin because while execution, this will be used. So instead of fetching plugin on every execution, plugin is fetched once during create action and stored as part of action (DBRef). Because of DBRef, eager loading would happen which would lead to plugin being present on get without loading plugin again.

This commit is contained in:
Trisha Anand 2019-09-03 11:36:49 +00:00
parent 7bc8948116
commit 4258f85a81
37 changed files with 173 additions and 137 deletions

View File

@ -3,8 +3,8 @@ package com.appsmith.server.configurations;
import com.appsmith.server.domains.LoginSource;
import com.appsmith.server.domains.User;
import com.appsmith.server.domains.UserState;
import com.appsmith.server.services.UserService;
import com.appsmith.server.services.TenantService;
import com.appsmith.server.services.UserService;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;

View File

@ -1,9 +1,9 @@
package com.appsmith.server.configurations;
import com.appsmith.server.services.UserService;
import com.appsmith.server.constants.Security;
import com.appsmith.server.services.TenantService;
import com.appsmith.server.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;

View File

@ -2,12 +2,17 @@ package com.appsmith.server.controllers;
import com.appsmith.server.domains.BaseDomain;
import com.appsmith.server.dtos.ResponseDto;
import com.appsmith.server.services.CrudService;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.services.CrudService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

View File

@ -1,8 +1,8 @@
package com.appsmith.server.controllers;
import com.appsmith.server.constants.Url;
import com.appsmith.server.domains.Layout;
import com.appsmith.server.services.LayoutService;
import com.appsmith.server.constants.Url;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

View File

@ -1,14 +1,18 @@
package com.appsmith.server.controllers;
import com.appsmith.server.constants.Url;
import com.appsmith.server.domains.Plugin;
import com.appsmith.server.domains.Tenant;
import com.appsmith.server.dtos.PluginTenantDTO;
import com.appsmith.server.dtos.ResponseDto;
import com.appsmith.server.services.PluginService;
import com.appsmith.server.constants.Url;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import javax.validation.Valid;

View File

@ -1,11 +1,15 @@
package com.appsmith.server.controllers;
import com.appsmith.server.constants.Url;
import com.appsmith.server.domains.Query;
import com.appsmith.server.dtos.CommandQueryParams;
import com.appsmith.server.services.QueryService;
import com.appsmith.server.constants.Url;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
@RestController

View File

@ -1,8 +1,8 @@
package com.appsmith.server.controllers;
import com.appsmith.server.services.ResourceService;
import com.appsmith.server.constants.Url;
import com.appsmith.server.domains.Resource;
import com.appsmith.server.services.ResourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

View File

@ -1,8 +1,8 @@
package com.appsmith.server.controllers;
import com.appsmith.server.constants.Url;
import com.appsmith.server.domains.Setting;
import com.appsmith.server.services.SettingService;
import com.appsmith.server.constants.Url;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

View File

@ -1,7 +1,7 @@
package com.appsmith.server.controllers;
import com.appsmith.server.domains.Tenant;
import com.appsmith.server.constants.Url;
import com.appsmith.server.domains.Tenant;
import com.appsmith.server.services.TenantService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;

View File

@ -1,9 +1,9 @@
package com.appsmith.server.controllers;
import com.appsmith.server.constants.Url;
import com.appsmith.server.domains.Widget;
import com.appsmith.server.dtos.ResponseDto;
import com.appsmith.server.services.WidgetService;
import com.appsmith.server.constants.Url;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;

View File

@ -5,7 +5,6 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
@Getter
@ -17,8 +16,9 @@ public class Action extends BaseDomain {
@Indexed(unique = true)
String name;
@DBRef
Resource resource;
String resourceId;
String pluginId;
ActionConfiguration actionConfiguration;
}

View File

@ -3,7 +3,11 @@ package com.appsmith.server.domains;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.annotation.*;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.domain.Persistable;
import java.util.Date;

View File

@ -5,7 +5,6 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
@Getter
@ -17,11 +16,9 @@ public class Resource extends BaseDomain {
@Indexed(unique = true)
String name;
@DBRef
Plugin plugin;
String pluginId;
@DBRef
Tenant tenant;
String tenantId;
ResourceConfiguration resourceConfiguration;

View File

@ -5,7 +5,6 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.mongodb.core.mapping.DBRef;
@Getter
@Setter
@ -13,8 +12,7 @@ import org.springframework.data.mongodb.core.mapping.DBRef;
@NoArgsConstructor
public class TenantPlugin extends BaseDomain {
@DBRef
private Plugin plugin;
private String pluginId;
TenantPluginStatus status;

View File

@ -1,6 +1,10 @@
package com.appsmith.server.dtos;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter

View File

@ -6,6 +6,6 @@ import lombok.Setter;
@Getter
@Setter
public class PluginTenantDTO {
String name;
String pluginId;
TenantPluginStatus status;
}

View File

@ -1,6 +1,10 @@
package com.appsmith.server.dtos;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;

View File

@ -9,6 +9,9 @@ public enum AppsmithError {
NO_RESOURCE_FOUND(404, 1000, "Unable to find {0} with id {1}"),
INVALID_PARAMETER(400, 4000, "Invalid parameter {0} provided in the input"),
PLUGIN_NOT_INSTALLED(400, 4001, "Plugin not installed for tenant {0}"),
PLUGIN_ID_NOT_GIVEN(400, 4002, "Missing plugin id. Please input correct plugin id"),
RESOURCE_ID_NOT_GIVEN(400, 4003, "Missing resource id. Please input correct resource id"),
INTERNAL_SERVER_ERROR(500, 5000, "Internal server error while processing request");
private Integer httpErrorCode;

View File

@ -1,6 +1,7 @@
package com.appsmith.server.exceptions;
import com.appsmith.server.dtos.ResponseDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ -13,20 +14,23 @@ import reactor.core.publisher.Mono;
* sending it to the client.
*/
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* This function only catches the AppsmithException type and formats it into ResponseEntity<ErrorDTO> object
* Ideally, we should only be throwing AppsmithException from our code. This ensures that we can standardize
* and set proper error messages and codes.
*
* @param e AppsmithException that will be caught by the function
* @param exchange ServerWebExchange contract in order to extract the response and set the http status code
* @return Mono<ResponseDto<ErrorDTO>>
* @return Mono<ResponseDto < ErrorDTO>>
*/
@ExceptionHandler
@ResponseBody
public Mono<ResponseDto<ErrorDTO>> catchAppsmithException(AppsmithException e, ServerWebExchange exchange) {
exchange.getResponse().setStatusCode(HttpStatus.resolve(e.getHttpStatus()));
log.error("", e);
return Mono.just(new ResponseDto<>(e.getHttpStatus(), new ErrorDTO(e.getAppErrorCode(), e.getMessage()), null, false));
}
@ -36,12 +40,13 @@ public class GlobalExceptionHandler {
*
* @param e Exception that will be caught by the function
* @param exchange ServerWebExchange contract in order to extract the response and set the http status code
* @return Mono<ResponseDto<ErrorDTO>>
* @return Mono<ResponseDto < ErrorDTO>>
*/
@ExceptionHandler
@ResponseBody
public Mono<ResponseDto<ErrorDTO>> catchException(Exception e, ServerWebExchange exchange) {
exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
log.error("", e);
return Mono.just(new ResponseDto<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), new ErrorDTO(AppsmithError.INTERNAL_SERVER_ERROR.getHttpErrorCode(),
AppsmithError.INTERNAL_SERVER_ERROR.getMessage()), null, false));
}

View File

@ -59,7 +59,7 @@ public class MDCFilter implements WebFilter {
private Mono<Void> addContextToHttpResponse(final ServerHttpResponse response) {
return Mono.subscriberContext().doOnNext(ctx -> {
if(!ctx.hasKey(LogHelper.CONTEXT_MAP)) {
if (!ctx.hasKey(LogHelper.CONTEXT_MAP)) {
return;
}
@ -67,7 +67,7 @@ public class MDCFilter implements WebFilter {
// Add all the request MDC keys to the response object
ctx.<Map<String, String>>get(LogHelper.CONTEXT_MAP)
.forEach((key, value) -> {
if(!key.contains(REQUEST_ID_LOG)) {
if (!key.contains(REQUEST_ID_LOG)) {
httpHeaders.add(MDC_HEADER_PREFIX + key, value);
} else {
httpHeaders.add(REQUEST_ID_HEADER, value);

View File

@ -1,14 +1,19 @@
package com.appsmith.server.plugins;
import com.appsmith.server.services.PluginExecutor;
import com.appsmith.server.domains.Query;
import com.appsmith.server.dtos.CommandQueryParams;
import com.appsmith.server.services.PluginExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;

View File

@ -1,9 +1,9 @@
package com.appsmith.server.plugins;
import com.appsmith.server.services.PluginExecutor;
import com.appsmith.server.domains.Property;
import com.appsmith.server.domains.Query;
import com.appsmith.server.dtos.CommandQueryParams;
import com.appsmith.server.services.PluginExecutor;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONObject;
import org.springframework.http.HttpHeaders;

View File

@ -7,4 +7,6 @@ import reactor.core.publisher.Mono;
@Repository
public interface PluginRepository extends BaseRepository<Plugin, String> {
Mono<Plugin> findByName(String name);
Mono<Plugin> findById(String id);
}

View File

@ -7,4 +7,6 @@ import reactor.core.publisher.Mono;
@Repository
public interface ResourceRepository extends BaseRepository<Resource, String> {
Mono<Resource> findByName(String name);
Mono<Resource> findById(String id);
}

View File

@ -7,4 +7,6 @@ import reactor.core.publisher.Mono;
@Repository
public interface TenantRepository extends BaseRepository<Tenant, String> {
Mono<Tenant> findByName(String name);
Mono<Tenant> findByIdAndPluginsPluginId(String tenantId, String pluginId);
}

View File

@ -8,5 +8,6 @@ import reactor.core.publisher.Mono;
public interface UserRepository extends BaseRepository<User, String> {
Mono<User> findByName(String name);
Mono<User> findByEmail(String email);
}

View File

@ -1,7 +1,9 @@
package com.appsmith.server.services;
import com.appsmith.server.domains.Action;
import com.appsmith.server.domains.Plugin;
import com.appsmith.server.domains.Resource;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.repositories.ActionRepository;
import lombok.extern.slf4j.Slf4j;
@ -20,25 +22,32 @@ public class ActionServiceImpl extends BaseService<ActionRepository, Action, Str
private final ActionRepository repository;
private final ResourceService resourceService;
private final PluginService pluginService;
@Autowired
public ActionServiceImpl(Scheduler scheduler, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, ActionRepository repository, ResourceService resourceService) {
public ActionServiceImpl(Scheduler scheduler, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, ActionRepository repository, ResourceService resourceService, PluginService pluginService) {
super(scheduler, mongoConverter, reactiveMongoTemplate, repository);
this.repository = repository;
this.resourceService = resourceService;
this.pluginService = pluginService;
}
@Override
public Mono<Action> create(@NotNull Action action) throws AppsmithException {
if (action.getId() != null) {
throw new AppsmithException("During create action, Id is not null. Can't create new action.");
} else if (action.getResourceId() == null) {
throw new AppsmithException(AppsmithError.RESOURCE_ID_NOT_GIVEN);
}
Mono<Resource> resourceMono = resourceService.findByName(action.getResource().getName());
Mono<Resource> resourceMono = resourceService.findById(action.getResourceId());
Mono<Plugin> pluginMono = resourceMono.flatMap(resource -> pluginService.findById(resource.getPluginId()));
return resourceMono
.map(resource -> {
action.setResource(resource);
return pluginMono
//Set plugin in the action before saving.
.map(plugin -> {
action.setPluginId(plugin.getId());
return action;
})
.flatMap(repository::save);

View File

@ -4,7 +4,6 @@ import com.appsmith.server.domains.BaseDomain;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.repositories.BaseRepository;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;

View File

@ -1,11 +1,11 @@
package com.appsmith.server.services;
import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheFactory;
import com.appsmith.server.domains.Query;
import com.appsmith.server.dtos.CommandQueryParams;
import com.appsmith.server.dtos.Param;
import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheFactory;
import reactor.core.publisher.Flux;
import java.io.StringReader;

View File

@ -4,7 +4,6 @@ import com.appsmith.server.domains.Plugin;
import com.appsmith.server.domains.PluginType;
import com.appsmith.server.domains.Tenant;
import com.appsmith.server.dtos.PluginTenantDTO;
import com.appsmith.server.exceptions.AppsmithException;
import reactor.core.publisher.Mono;
public interface PluginService extends CrudService<Plugin, String> {
@ -25,4 +24,6 @@ public interface PluginService extends CrudService<Plugin, String> {
public Mono<Plugin> findByName(String name);
public Mono<Plugin> findById(String id);
}

View File

@ -12,15 +12,11 @@ import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.repositories.PluginRepository;
import com.appsmith.server.repositories.UserRepository;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
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.stereotype.Service;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
@ -80,14 +76,17 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
@Override
public Mono<Tenant> installPlugin(PluginTenantDTO pluginTenantDTO) {
return pluginRepository
.findByName(pluginTenantDTO.getName())
.flatMap(plugin1 -> storeTenantPlugin(plugin1, pluginTenantDTO.getStatus()))
if (pluginTenantDTO.getPluginId() == null) {
return Mono.error(new AppsmithException(AppsmithError.PLUGIN_ID_NOT_GIVEN));
}
return Mono.just(pluginTenantDTO)
.flatMap(plugin -> storeTenantPlugin(plugin, pluginTenantDTO.getStatus()))
.switchIfEmpty(Mono.empty());
}
@Override
public Mono<Tenant> uninstallPlugin(PluginTenantDTO plugin) {
public Mono<Tenant> uninstallPlugin(PluginTenantDTO pluginDTO) {
/*TODO
* Tenant & user association is being mocked here by forcefully
* only using a hardcoded tenant. This needs to be replaced by
@ -102,36 +101,28 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
* be stored as part of user and this tenant should be used to store
* the installed plugin or to delete plugin during uninstallation.
*/
Mono<Tenant> tenantMono = tenantService.findById(tenantId);
if (pluginDTO.getPluginId() == null) {
return Mono.error(new AppsmithException(AppsmithError.PLUGIN_ID_NOT_GIVEN));
}
//Find the tenant using id and plugin id -> This is to find if the tenant has the plugin installed
Mono<Tenant> tenantMono = tenantService.findByIdAndPluginsPluginId(tenantId, pluginDTO.getPluginId());
return tenantMono
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.PLUGIN_NOT_INSTALLED, tenantId)))
//In case the plugin is not found for the tenant, the tenantMono would not emit and the rest of the flow would stop
//i.e. the rest of the code flow would only happen when there is a plugin found for the tenant that can
//be uninstalled.
.map(tenant -> {
List<TenantPlugin> tenantPluginList = tenant.getPlugins();
if (tenantPluginList == null || tenantPluginList.isEmpty()) {
return tenant;
}
for (TenantPlugin listPlugin : tenantPluginList) {
if (listPlugin.getPlugin().getName().equals(plugin.getName())) {
log.debug("Plugin {} found. Uninstalling now from Tenant {}.",
plugin.getName(), tenant.getName());
tenantPluginList.remove(listPlugin);
tenantPluginList.removeIf(listPlugin -> listPlugin.getPluginId().equals(pluginDTO.getPluginId()));
tenant.setPlugins(tenantPluginList);
return tenant;
}
}
log.debug("Plugin {} not found. Can't uninstall a plugin which is not installed",
plugin.getName());
return tenant;
})
/* TODO
* Extra save is happening below in the edge case scenario of a plugin
* which needs to be removed from the installed list, didnt exist in this list
* to be begin with. Small optimization opportunity.
*/
.flatMap(tenantService::save);
}
private Mono<Tenant> storeTenantPlugin(Plugin plugin, TenantPluginStatus status) {
private Mono<Tenant> storeTenantPlugin(PluginTenantDTO pluginDTO, TenantPluginStatus status) {
/*TODO
* Tenant & user association is being mocked here by forcefully
* only using a hardcoded tenant. This needs to be replaced by
@ -144,40 +135,37 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
* .map(Authentication::getPrincipal);
* Once the user has been pulled using this, tenant should already
* be stored as part of user and this tenant should be used to store
* the installed plugin or to delete plugin during uninstallation.
* the installed plugin or to delete plugin during uninstalling.
*/
Mono<Tenant> tenantMono = tenantService.findById(tenantId);
Mono<Object> userObjectMono = ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
.map(Authentication::getPrincipal);
//Find the tenant using id and plugin id -> This is to find if the tenant already has the plugin installed
Mono<Tenant> tenantMono = tenantService.findByIdAndPluginsPluginId(tenantId, pluginDTO.getPluginId());
return Mono.zip(tenantMono, userObjectMono, (tenant, user) -> {
return tenantMono
.switchIfEmpty(Mono.defer(() -> {
//If the plugin is not found in the tenant, its not already installed. Install now.
return tenantService.findById(tenantId).map(tenant -> {
List<TenantPlugin> tenantPluginList = tenant.getPlugins();
if (tenantPluginList == null) {
tenantPluginList = new ArrayList<TenantPlugin>();
}
for (TenantPlugin listPlugin : tenantPluginList) {
if (listPlugin.getPlugin().getName().equals(plugin.getName())) {
log.debug("Plugin {} is already installed for Tenant {}. Don't add again.",
plugin.getName(), tenant.getName());
return tenant;
}
}
log.debug("Installing plugin {} for tenant {}", pluginDTO.getPluginId(), tenant.getName());
TenantPlugin tenantPlugin = new TenantPlugin();
//Set an ID in the nested document so that installed plugins can be referred to uniquely using IDs
ObjectId objectId = new ObjectId();
tenantPlugin.setId(objectId.toString());
tenantPlugin.setPlugin(plugin);
tenantPlugin.setPluginId(pluginDTO.getPluginId());
tenantPlugin.setStatus(status);
tenantPluginList.add(tenantPlugin);
tenant.setPlugins(tenantPluginList);
return tenant;
}).flatMap(tenantService::save);
}));
}
public Mono<Plugin> findByName(String name) {
return repository.findByName(name);
}
@Override
public Mono<Plugin> findById(String id) {
return repository.findById(id);
}
}

View File

@ -4,5 +4,8 @@ import com.appsmith.server.domains.Resource;
import reactor.core.publisher.Mono;
public interface ResourceService extends CrudService<Resource, String> {
Mono<Resource> findByName(String name);
Mono<Resource> findById(String id);
}

View File

@ -1,9 +1,7 @@
package com.appsmith.server.services;
import com.appsmith.server.domains.Plugin;
import com.appsmith.server.domains.Resource;
import com.appsmith.server.domains.Tenant;
import com.appsmith.server.domains.TenantPlugin;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.repositories.ResourceRepository;
@ -17,8 +15,6 @@ import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@Slf4j
@Service
@ -43,36 +39,22 @@ public class ResourceServiceImpl extends BaseService<ResourceRepository, Resourc
public Mono<Resource> create(@NotNull Resource resource) throws AppsmithException {
if (resource.getId() != null) {
throw new AppsmithException(AppsmithError.INVALID_PARAMETER, "id");
} else if (resource.getPluginId() == null) {
throw new AppsmithException(AppsmithError.PLUGIN_ID_NOT_GIVEN);
}
Mono<Tenant> tenantMono = tenantService.findById(tenantId);
Mono<Plugin> pluginMono = pluginService.findByName(resource.getPlugin().getName());
Mono<Resource> updatedResourceMono = Mono.zip(tenantMono, pluginMono, (tenant, plugin) -> {
resource.setTenant(tenant);
resource.setPlugin(plugin);
return resource;
Mono<Tenant> tenantMono = tenantService.findByIdAndPluginsPluginId(tenantId, resource.getPluginId());
//Add tenant id to the resource.
Mono<Resource> updatedResourceMono = Mono.just(resource)
.map(updatedResource -> {
updatedResource.setTenantId(tenantId);
return updatedResource;
});
return updatedResourceMono
.filter(updatedResource -> {
AtomicReference<Boolean> temp = new AtomicReference<>(false);
tenantMono.map(tenant -> {
List<TenantPlugin> tenantPlugins = tenant.getPlugins();
if (tenantPlugins == null || tenantPlugins.isEmpty()) {
temp.set(false);
return temp;
}
for (TenantPlugin tenantPlugin : tenantPlugins) {
if (tenantPlugin.getPlugin().getName().equals(resource.getPlugin().getName())) {
temp.set(true);
return temp;
}
}
temp.set(false);
return temp;
}).block();
return temp.get();
})
return tenantMono
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.PLUGIN_NOT_INSTALLED, tenantId)))
.then(updatedResourceMono)
.flatMap(repository::save);
}
@ -80,4 +62,9 @@ public class ResourceServiceImpl extends BaseService<ResourceRepository, Resourc
public Mono<Resource> findByName(String name) {
return repository.findByName(name);
}
@Override
public Mono<Resource> findById(String id) {
return repository.findById(id);
}
}

View File

@ -12,4 +12,6 @@ public interface TenantService extends CrudService<Tenant, String> {
Mono<Tenant> findById(String id);
Mono<Tenant> save(Tenant tenant);
Mono<Tenant> findByIdAndPluginsPluginId(String tenantId, String pluginId);
}

View File

@ -91,5 +91,10 @@ public class TenantServiceImpl extends BaseService<TenantRepository, Tenant, Str
return repository.save(tenant);
}
@Override
public Mono<Tenant> findByIdAndPluginsPluginId(String tenantId, String pluginId) {
return repository.findByIdAndPluginsPluginId(tenantId, pluginId);
}
}

View File

@ -6,6 +6,8 @@ import reactor.core.publisher.Mono;
public interface UserService extends CrudService<User, String> {
Mono<User> findByUsername(String name);
Mono<User> findByEmail(String email);
Mono<User> save(User newUser);
}