diff --git a/app/server/src/main/java/com/appsmith/server/configurations/ClientUserRepository.java b/app/server/src/main/java/com/appsmith/server/configurations/ClientUserRepository.java index d630f3a22e..343b0bd942 100644 --- a/app/server/src/main/java/com/appsmith/server/configurations/ClientUserRepository.java +++ b/app/server/src/main/java/com/appsmith/server/configurations/ClientUserRepository.java @@ -3,7 +3,7 @@ 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.TenantService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.UserService; import org.springframework.context.annotation.Configuration; import org.springframework.security.core.Authentication; @@ -46,10 +46,10 @@ public class ClientUserRepository implements ServerOAuth2AuthorizedClientReposit WebSessionServerOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS"; private final String sessionAttributeName = DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME; UserService userService; - TenantService tenantService; - public ClientUserRepository(UserService userService, TenantService tenantService) { + OrganizationService organizationService; + public ClientUserRepository(UserService userService, OrganizationService organizationService) { this.userService = userService; - this.tenantService = tenantService; + this.organizationService = organizationService; } @Override @@ -93,15 +93,15 @@ public class ClientUserRepository implements ServerOAuth2AuthorizedClientReposit newUser.setIsEnabled(true); /** TODO - * Tenant here is being hardcoded. This is a stop gap measure - * A flow needs to be added to connect a User to a Tenant. Once - * that is done, during the login, the tenant should be picked up + * Organization here is being hardcoded. This is a stop gap measure + * A flow needs to be added to connect a User to a Organization. Once + * that is done, during the login, the organization should be picked up * and a user should be hence created. */ - return tenantService.findById("5d3e90a2dfec7c00047a81ea") - .map(tenant -> { - newUser.setTenant(tenant); + return organizationService.findById("5d3e90a2dfec7c00047a81ea") + .map(organization -> { + newUser.setOrganization(organization); return newUser; }) .then(userService.findByEmail(user.getEmail())) diff --git a/app/server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java b/app/server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java index 30585b1c82..f1a540afaa 100644 --- a/app/server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java +++ b/app/server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java @@ -2,7 +2,7 @@ package com.appsmith.server.configurations; import com.appsmith.server.constants.Security; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -27,7 +27,7 @@ public class SecurityConfig { private UserService userService; @Autowired - private TenantService tenantService; + private OrganizationService organizationService; /** * This configuration enables CORS requests for the most common HTTP Methods @@ -72,7 +72,7 @@ public class SecurityConfig { .authenticated() .and().httpBasic() .and().oauth2Login() - .authorizedClientRepository(new ClientUserRepository(userService, tenantService)) + .authorizedClientRepository(new ClientUserRepository(userService, organizationService)) .and().formLogin() .and().build(); } diff --git a/app/server/src/main/java/com/appsmith/server/constants/FieldName.java b/app/server/src/main/java/com/appsmith/server/constants/FieldName.java index ba3ce6fc57..1ab278a58a 100644 --- a/app/server/src/main/java/com/appsmith/server/constants/FieldName.java +++ b/app/server/src/main/java/com/appsmith/server/constants/FieldName.java @@ -1,7 +1,7 @@ package com.appsmith.server.constants; public class FieldName { - public static String TENANT = "tenant"; + public static String ORGANIZATION = "organization"; public static String ID = "id"; public static String NAME = "name"; } diff --git a/app/server/src/main/java/com/appsmith/server/constants/Url.java b/app/server/src/main/java/com/appsmith/server/constants/Url.java index 1101c61f2f..940faa9fab 100644 --- a/app/server/src/main/java/com/appsmith/server/constants/Url.java +++ b/app/server/src/main/java/com/appsmith/server/constants/Url.java @@ -4,7 +4,7 @@ public interface Url { String BASE_URL = "/api"; String VERSION = "/v1"; String WIDGET_URL = BASE_URL + VERSION + "/widgets"; - String TENANT_URL = BASE_URL + VERSION + "/tenants"; + String ORGANIZATION_URL = BASE_URL + VERSION + "/organizations"; String LAYOUT_URL = BASE_URL + VERSION + "/layouts"; String PLUGIN_URL = BASE_URL + VERSION + "/plugins"; String QUERY_URL = BASE_URL + VERSION + "/queries"; diff --git a/app/server/src/main/java/com/appsmith/server/controllers/OrganizationController.java b/app/server/src/main/java/com/appsmith/server/controllers/OrganizationController.java new file mode 100644 index 0000000000..630deaf625 --- /dev/null +++ b/app/server/src/main/java/com/appsmith/server/controllers/OrganizationController.java @@ -0,0 +1,20 @@ +package com.appsmith.server.controllers; + +import com.appsmith.server.constants.Url; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.services.OrganizationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping(Url.ORGANIZATION_URL) +public class OrganizationController extends BaseController { + + + @Autowired + public OrganizationController(OrganizationService organizationService) { + super(organizationService); + } + +} diff --git a/app/server/src/main/java/com/appsmith/server/controllers/PluginController.java b/app/server/src/main/java/com/appsmith/server/controllers/PluginController.java index ee4def6e30..3f55c6bef6 100644 --- a/app/server/src/main/java/com/appsmith/server/controllers/PluginController.java +++ b/app/server/src/main/java/com/appsmith/server/controllers/PluginController.java @@ -1,9 +1,9 @@ package com.appsmith.server.controllers; import com.appsmith.server.constants.Url; +import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.Plugin; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.dtos.PluginTenantDTO; +import com.appsmith.server.dtos.PluginOrgDTO; import com.appsmith.server.dtos.ResponseDto; import com.appsmith.server.services.PluginService; import org.springframework.beans.factory.annotation.Autowired; @@ -29,16 +29,16 @@ public class PluginController extends BaseController> install(@Valid @RequestBody PluginTenantDTO plugin) { + public Mono> install(@Valid @RequestBody PluginOrgDTO plugin) { return service.installPlugin(plugin) - .map(tenant -> new ResponseDto<>(HttpStatus.CREATED.value(), tenant, null)); + .map(organization -> new ResponseDto<>(HttpStatus.CREATED.value(), organization, null)); } @PostMapping("/uninstall") @ResponseStatus(HttpStatus.CREATED) - public Mono> uninstall(@Valid @RequestBody PluginTenantDTO plugin) { + public Mono> uninstall(@Valid @RequestBody PluginOrgDTO plugin) { return service.uninstallPlugin(plugin) - .map(tenant -> new ResponseDto<>(HttpStatus.CREATED.value(), tenant, null)); + .map(organization -> new ResponseDto<>(HttpStatus.CREATED.value(), organization, null)); } } diff --git a/app/server/src/main/java/com/appsmith/server/controllers/TenantController.java b/app/server/src/main/java/com/appsmith/server/controllers/TenantController.java deleted file mode 100644 index 1ebc8cbbab..0000000000 --- a/app/server/src/main/java/com/appsmith/server/controllers/TenantController.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.appsmith.server.controllers; - -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; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping(Url.TENANT_URL) -public class TenantController extends BaseController { - - - @Autowired - public TenantController(TenantService tenantService) { - super(tenantService); - } - -} diff --git a/app/server/src/main/java/com/appsmith/server/domains/Tenant.java b/app/server/src/main/java/com/appsmith/server/domains/Organization.java similarity index 73% rename from app/server/src/main/java/com/appsmith/server/domains/Tenant.java rename to app/server/src/main/java/com/appsmith/server/domains/Organization.java index e7f80c01bc..8615a16d95 100644 --- a/app/server/src/main/java/com/appsmith/server/domains/Tenant.java +++ b/app/server/src/main/java/com/appsmith/server/domains/Organization.java @@ -15,7 +15,7 @@ import java.util.List; @ToString @NoArgsConstructor @Document -public class Tenant extends BaseDomain { +public class Organization extends BaseDomain { private String domain; @@ -24,8 +24,8 @@ public class Tenant extends BaseDomain { private String website; - private List tenantSettings; + private List organizationSettings; - private List plugins; + private List plugins; } diff --git a/app/server/src/main/java/com/appsmith/server/domains/TenantPlugin.java b/app/server/src/main/java/com/appsmith/server/domains/OrganizationPlugin.java similarity index 59% rename from app/server/src/main/java/com/appsmith/server/domains/TenantPlugin.java rename to app/server/src/main/java/com/appsmith/server/domains/OrganizationPlugin.java index e30176ac96..6e31a0bcb2 100644 --- a/app/server/src/main/java/com/appsmith/server/domains/TenantPlugin.java +++ b/app/server/src/main/java/com/appsmith/server/domains/OrganizationPlugin.java @@ -1,6 +1,6 @@ package com.appsmith.server.domains; -import com.appsmith.server.dtos.TenantPluginStatus; +import com.appsmith.server.dtos.OrganizationPluginStatus; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -10,10 +10,10 @@ import lombok.ToString; @Setter @ToString @NoArgsConstructor -public class TenantPlugin extends BaseDomain { +public class OrganizationPlugin extends BaseDomain { private String pluginId; - TenantPluginStatus status; + OrganizationPluginStatus status; } diff --git a/app/server/src/main/java/com/appsmith/server/domains/TenantSetting.java b/app/server/src/main/java/com/appsmith/server/domains/OrganizationSetting.java similarity index 89% rename from app/server/src/main/java/com/appsmith/server/domains/TenantSetting.java rename to app/server/src/main/java/com/appsmith/server/domains/OrganizationSetting.java index 14c3a38d9b..1b7cf83d52 100644 --- a/app/server/src/main/java/com/appsmith/server/domains/TenantSetting.java +++ b/app/server/src/main/java/com/appsmith/server/domains/OrganizationSetting.java @@ -15,7 +15,7 @@ import org.springframework.data.mongodb.core.mapping.DBRef; @Setter @ToString @NoArgsConstructor -public class TenantSetting extends BaseDomain { +public class OrganizationSetting extends BaseDomain { @DBRef private Setting setting; diff --git a/app/server/src/main/java/com/appsmith/server/domains/Resource.java b/app/server/src/main/java/com/appsmith/server/domains/Resource.java index bf9be7404a..a8a9d97448 100644 --- a/app/server/src/main/java/com/appsmith/server/domains/Resource.java +++ b/app/server/src/main/java/com/appsmith/server/domains/Resource.java @@ -18,7 +18,7 @@ public class Resource extends BaseDomain { String pluginId; - String tenantId; + String organizationId; ResourceConfiguration resourceConfiguration; diff --git a/app/server/src/main/java/com/appsmith/server/domains/Setting.java b/app/server/src/main/java/com/appsmith/server/domains/Setting.java index df6290adae..fb944ca0cc 100644 --- a/app/server/src/main/java/com/appsmith/server/domains/Setting.java +++ b/app/server/src/main/java/com/appsmith/server/domains/Setting.java @@ -19,6 +19,6 @@ public class Setting extends BaseDomain { private String defaultValue; - private Boolean isTenantSetting; + private Boolean isOrganizationSetting; } diff --git a/app/server/src/main/java/com/appsmith/server/domains/User.java b/app/server/src/main/java/com/appsmith/server/domains/User.java index ab087e4bc1..1d2e32948d 100644 --- a/app/server/src/main/java/com/appsmith/server/domains/User.java +++ b/app/server/src/main/java/com/appsmith/server/domains/User.java @@ -35,7 +35,7 @@ public class User extends BaseDomain implements UserDetails { private Boolean isEnabled; - private Tenant tenant; + private Organization organization; @Override public Collection getAuthorities() { diff --git a/app/server/src/main/java/com/appsmith/server/dtos/TenantPluginStatus.java b/app/server/src/main/java/com/appsmith/server/dtos/OrganizationPluginStatus.java similarity index 62% rename from app/server/src/main/java/com/appsmith/server/dtos/TenantPluginStatus.java rename to app/server/src/main/java/com/appsmith/server/dtos/OrganizationPluginStatus.java index 1f8cf9be01..23b0a55b98 100644 --- a/app/server/src/main/java/com/appsmith/server/dtos/TenantPluginStatus.java +++ b/app/server/src/main/java/com/appsmith/server/dtos/OrganizationPluginStatus.java @@ -1,5 +1,5 @@ package com.appsmith.server.dtos; -public enum TenantPluginStatus { +public enum OrganizationPluginStatus { FREE, TRIAL, ACTIVATED } diff --git a/app/server/src/main/java/com/appsmith/server/dtos/PluginTenantDTO.java b/app/server/src/main/java/com/appsmith/server/dtos/PluginOrgDTO.java similarity index 63% rename from app/server/src/main/java/com/appsmith/server/dtos/PluginTenantDTO.java rename to app/server/src/main/java/com/appsmith/server/dtos/PluginOrgDTO.java index f5dd221fd8..69be1b4c88 100644 --- a/app/server/src/main/java/com/appsmith/server/dtos/PluginTenantDTO.java +++ b/app/server/src/main/java/com/appsmith/server/dtos/PluginOrgDTO.java @@ -5,7 +5,9 @@ import lombok.Setter; @Getter @Setter -public class PluginTenantDTO { +public class PluginOrgDTO { + String pluginId; - TenantPluginStatus status; + + OrganizationPluginStatus status; } diff --git a/app/server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java b/app/server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java index 1b09e9e727..5f32ce5b82 100644 --- a/app/server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java +++ b/app/server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java @@ -9,7 +9,7 @@ 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_NOT_INSTALLED(400, 4001, "Plugin not installed for organization {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"); diff --git a/app/server/src/main/java/com/appsmith/server/repositories/OrganizationRepository.java b/app/server/src/main/java/com/appsmith/server/repositories/OrganizationRepository.java new file mode 100644 index 0000000000..2fd02bb518 --- /dev/null +++ b/app/server/src/main/java/com/appsmith/server/repositories/OrganizationRepository.java @@ -0,0 +1,12 @@ +package com.appsmith.server.repositories; + +import com.appsmith.server.domains.Organization; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Mono; + +@Repository +public interface OrganizationRepository extends BaseRepository { + Mono findByName(String name); + + Mono findByIdAndPluginsPluginId(String organizationId, String pluginId); +} diff --git a/app/server/src/main/java/com/appsmith/server/repositories/TenantRepository.java b/app/server/src/main/java/com/appsmith/server/repositories/TenantRepository.java deleted file mode 100644 index 8d399aac81..0000000000 --- a/app/server/src/main/java/com/appsmith/server/repositories/TenantRepository.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.appsmith.server.repositories; - -import com.appsmith.server.domains.Tenant; -import org.springframework.stereotype.Repository; -import reactor.core.publisher.Mono; - -@Repository -public interface TenantRepository extends BaseRepository { - Mono findByName(String name); - - Mono findByIdAndPluginsPluginId(String tenantId, String pluginId); -} diff --git a/app/server/src/main/java/com/appsmith/server/services/BaseService.java b/app/server/src/main/java/com/appsmith/server/services/BaseService.java index 261ebf2d92..e965d91713 100644 --- a/app/server/src/main/java/com/appsmith/server/services/BaseService.java +++ b/app/server/src/main/java/com/appsmith/server/services/BaseService.java @@ -16,10 +16,8 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.scheduler.Scheduler; -import javax.validation.ConstraintViolation; import javax.validation.Validator; import java.util.Map; -import java.util.Set; public abstract class BaseService implements CrudService { diff --git a/app/server/src/main/java/com/appsmith/server/services/OrganizationService.java b/app/server/src/main/java/com/appsmith/server/services/OrganizationService.java new file mode 100644 index 0000000000..6e907944f8 --- /dev/null +++ b/app/server/src/main/java/com/appsmith/server/services/OrganizationService.java @@ -0,0 +1,17 @@ +package com.appsmith.server.services; + +import com.appsmith.server.domains.Organization; +import reactor.core.publisher.Mono; + +public interface OrganizationService extends CrudService { + + Mono getByName(String name); + + Mono create(Organization object); + + Mono findById(String id); + + Mono save(Organization organization); + + Mono findByIdAndPluginsPluginId(String organizationId, String pluginId); +} diff --git a/app/server/src/main/java/com/appsmith/server/services/OrganizationServiceImpl.java b/app/server/src/main/java/com/appsmith/server/services/OrganizationServiceImpl.java new file mode 100644 index 0000000000..f3915a23d9 --- /dev/null +++ b/app/server/src/main/java/com/appsmith/server/services/OrganizationServiceImpl.java @@ -0,0 +1,110 @@ +package com.appsmith.server.services; + +import com.appsmith.server.constants.FieldName; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationSetting; +import com.appsmith.server.domains.Setting; +import com.appsmith.server.exceptions.AppsmithError; +import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.repositories.OrganizationRepository; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Scheduler; + +import javax.validation.Validator; +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Service +public class OrganizationServiceImpl extends BaseService implements OrganizationService { + + private final OrganizationRepository repository; + private final SettingService settingService; + + @Autowired + public OrganizationServiceImpl(Scheduler scheduler, + Validator validator, + MongoConverter mongoConverter, + ReactiveMongoTemplate reactiveMongoTemplate, + OrganizationRepository repository, + SettingService settingService) { + super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository); + this.repository = repository; + this.settingService = settingService; + } + + @Override + public Mono getByName(String name) { + return repository.findByName(name); + } + + /* + * Create needs to first fetch and embed Setting in OrganizationSetting + * for the settings that have diverged from the default. Once the + * settings has been embedded in all the organization settings, the library + * function is called to store the enhanced organization object. + */ + @Override + public Mono create(Organization organization) { + if (organization == null) { + return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ORGANIZATION)); + } + + log.debug("Going to create the organization {}", organization.getName()); + return Mono.just(organization) + .flatMap(this::validateObject) + //transform the organization data to embed setting object in each object in organizationSetting list. + .flatMap(this::enhanceOrganizationSettingList) + //Call the library function to save the updated organization + .flatMap(repository::save); + } + + private Mono enhanceOrganizationSettingList(Organization organization) { + + if (organization.getOrganizationSettings() == null) { + organization.setOrganizationSettings(new ArrayList<>()); + } + + Flux organizationSettingFlux = Flux.fromIterable(organization.getOrganizationSettings()); + // For each organization setting, fetch and embed the setting, and once all the organization setting are done, collect it + // back into a single list of organization settings. + Mono> listMono = organizationSettingFlux.flatMap(this::fetchAndEmbedSetting).collectList(); + return listMono.map(list -> { + organization.setOrganizationSettings(list); + return list; + }).thenReturn(organization); + } + + private Mono fetchAndEmbedSetting(OrganizationSetting organizationSetting) { + + String key = organizationSetting.getSetting().getKey(); + Mono setting = settingService.getByKey(key); + return setting.map(setting1 -> { + organizationSetting.setSetting(setting1); + return organizationSetting; + }); + } + + @Override + public Mono findById(String id) { + return repository.findById(id); + } + + @Override + public Mono save(Organization organization) { + return repository.save(organization); + } + + @Override + public Mono findByIdAndPluginsPluginId(String organizationId, String pluginId) { + return repository.findByIdAndPluginsPluginId(organizationId, pluginId); + } + +} + diff --git a/app/server/src/main/java/com/appsmith/server/services/PluginService.java b/app/server/src/main/java/com/appsmith/server/services/PluginService.java index fcf16fc17d..a9ee7e537f 100644 --- a/app/server/src/main/java/com/appsmith/server/services/PluginService.java +++ b/app/server/src/main/java/com/appsmith/server/services/PluginService.java @@ -1,9 +1,9 @@ package com.appsmith.server.services; +import com.appsmith.server.domains.Organization; 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.dtos.PluginOrgDTO; import reactor.core.publisher.Mono; public interface PluginService extends CrudService { @@ -18,9 +18,9 @@ public interface PluginService extends CrudService { */ PluginExecutor getPluginExecutor(PluginType pluginType, String className); - public Mono installPlugin(PluginTenantDTO plugin); + public Mono installPlugin(PluginOrgDTO plugin); - public Mono uninstallPlugin(PluginTenantDTO plugin); + public Mono uninstallPlugin(PluginOrgDTO plugin); public Mono findByName(String name); diff --git a/app/server/src/main/java/com/appsmith/server/services/PluginServiceImpl.java b/app/server/src/main/java/com/appsmith/server/services/PluginServiceImpl.java index bcf5476058..069e56d71d 100644 --- a/app/server/src/main/java/com/appsmith/server/services/PluginServiceImpl.java +++ b/app/server/src/main/java/com/appsmith/server/services/PluginServiceImpl.java @@ -1,12 +1,12 @@ package com.appsmith.server.services; import com.appsmith.server.configurations.ClientUserRepository; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationPlugin; import com.appsmith.server.domains.Plugin; import com.appsmith.server.domains.PluginType; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantPlugin; -import com.appsmith.server.dtos.PluginTenantDTO; -import com.appsmith.server.dtos.TenantPluginStatus; +import com.appsmith.server.dtos.OrganizationPluginStatus; +import com.appsmith.server.dtos.PluginOrgDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.repositories.PluginRepository; @@ -33,10 +33,10 @@ public class PluginServiceImpl extends BaseService installPlugin(PluginTenantDTO pluginTenantDTO) { - if (pluginTenantDTO.getPluginId() == null) { + public Mono installPlugin(PluginOrgDTO pluginOrgDTO) { + if (pluginOrgDTO.getPluginId() == null) { return Mono.error(new AppsmithException(AppsmithError.PLUGIN_ID_NOT_GIVEN)); } - return Mono.just(pluginTenantDTO) - .flatMap(plugin -> storeTenantPlugin(plugin, pluginTenantDTO.getStatus())) + return Mono.just(pluginOrgDTO) + .flatMap(plugin -> storeOrganizationPlugin(plugin, pluginOrgDTO.getStatus())) .switchIfEmpty(Mono.empty()); } @Override - public Mono uninstallPlugin(PluginTenantDTO pluginDTO) { + public Mono uninstallPlugin(PluginOrgDTO pluginDTO) { /*TODO - * Tenant & user association is being mocked here by forcefully - * only using a hardcoded tenant. This needs to be replaced by - * a user-tenant association flow. The Tenant needs to be picked + * Organization & user association is being mocked here by forcefully + * only using a hardcoded organization. This needs to be replaced by + * a user-organization association flow. The Organization needs to be picked * up from a user object. This is being used in install/uninstall - * plugin from a tenant flow. Instead, the current user should be read + * plugin from a organization flow. Instead, the current user should be read * using the following : * ReactiveSecurityContextHolder.getContext() * .map(SecurityContext::getAuthentication) * .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 + * Once the user has been pulled using this, organization should already + * be stored as part of user and this organization should be used to store * the installed plugin or to delete plugin during uninstallation. */ 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 tenantMono = tenantService.findByIdAndPluginsPluginId(tenantId, pluginDTO.getPluginId()); + //Find the organization using id and plugin id -> This is to find if the organization has the plugin installed + Mono organizationMono = organizationService.findByIdAndPluginsPluginId(organizationId, 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 + return organizationMono + .switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.PLUGIN_NOT_INSTALLED, organizationId))) + //In case the plugin is not found for the organization, the organizationMono 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 organization that can //be uninstalled. - .map(tenant -> { - List tenantPluginList = tenant.getPlugins(); - tenantPluginList.removeIf(listPlugin -> listPlugin.getPluginId().equals(pluginDTO.getPluginId())); - tenant.setPlugins(tenantPluginList); - return tenant; + .map(organization -> { + List organizationPluginList = organization.getPlugins(); + organizationPluginList.removeIf(listPlugin -> listPlugin.getPluginId().equals(pluginDTO.getPluginId())); + organization.setPlugins(organizationPluginList); + return organization; }) - .flatMap(tenantService::save); + .flatMap(organizationService::save); } - private Mono storeTenantPlugin(PluginTenantDTO pluginDTO, TenantPluginStatus status) { + private Mono storeOrganizationPlugin(PluginOrgDTO pluginDTO, OrganizationPluginStatus status) { /*TODO - * Tenant & user association is being mocked here by forcefully - * only using a hardcoded tenant. This needs to be replaced by - * a user-tenant association flow. The Tenant needs to be picked + * Organization & user association is being mocked here by forcefully + * only using a hardcoded organization. This needs to be replaced by + * a user-organization association flow. The Organization needs to be picked * up from a user object. This is being used in install/uninstall - * plugin from a tenant flow. Instead, the current user should be read + * plugin from a organization flow. Instead, the current user should be read * using the following : * ReactiveSecurityContextHolder.getContext() * .map(SecurityContext::getAuthentication) * .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 + * Once the user has been pulled using this, organization should already + * be stored as part of user and this organization should be used to store * the installed plugin or to delete plugin during uninstalling. */ - //Find the tenant using id and plugin id -> This is to find if the tenant already has the plugin installed - Mono tenantMono = tenantService.findByIdAndPluginsPluginId(tenantId, pluginDTO.getPluginId()); + //Find the organization using id and plugin id -> This is to find if the organization already has the plugin installed + Mono organizationMono = organizationService.findByIdAndPluginsPluginId(organizationId, pluginDTO.getPluginId()); - return tenantMono + return organizationMono .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 tenantPluginList = tenant.getPlugins(); - if (tenantPluginList == null) { - tenantPluginList = new ArrayList(); + //If the plugin is not found in the organization, its not already installed. Install now. + return organizationService.findById(organizationId).map(organization -> { + List organizationPluginList = organization.getPlugins(); + if (organizationPluginList == null) { + organizationPluginList = new ArrayList(); } - log.debug("Installing plugin {} for tenant {}", pluginDTO.getPluginId(), tenant.getName()); - TenantPlugin tenantPlugin = new TenantPlugin(); - tenantPlugin.setPluginId(pluginDTO.getPluginId()); - tenantPlugin.setStatus(status); - tenantPluginList.add(tenantPlugin); - tenant.setPlugins(tenantPluginList); - return tenant; - }).flatMap(tenantService::save); + log.debug("Installing plugin {} for organization {}", pluginDTO.getPluginId(), organization.getName()); + OrganizationPlugin organizationPlugin = new OrganizationPlugin(); + organizationPlugin.setPluginId(pluginDTO.getPluginId()); + organizationPlugin.setStatus(status); + organizationPluginList.add(organizationPlugin); + organization.setPlugins(organizationPluginList); + return organization; + }).flatMap(organizationService::save); })); } diff --git a/app/server/src/main/java/com/appsmith/server/services/ResourceServiceImpl.java b/app/server/src/main/java/com/appsmith/server/services/ResourceServiceImpl.java index 8e8216744c..71bca4545c 100644 --- a/app/server/src/main/java/com/appsmith/server/services/ResourceServiceImpl.java +++ b/app/server/src/main/java/com/appsmith/server/services/ResourceServiceImpl.java @@ -1,7 +1,7 @@ package com.appsmith.server.services; +import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.Resource; -import com.appsmith.server.domains.Tenant; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.repositories.ResourceRepository; @@ -21,18 +21,18 @@ import javax.validation.constraints.NotNull; @Service public class ResourceServiceImpl extends BaseService implements ResourceService { - @Value("${tenant.id}") - private String tenantId; + @Value("${organization.id}") + private String organizationId; private final ResourceRepository repository; - private final TenantService tenantService; + private final OrganizationService organizationService; private final PluginService pluginService; @Autowired - public ResourceServiceImpl(Scheduler scheduler, Validator validator, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, ResourceRepository repository, TenantService tenantService, PluginService pluginService) { + public ResourceServiceImpl(Scheduler scheduler, Validator validator, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, ResourceRepository repository, OrganizationService organizationService, PluginService pluginService) { super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository); this.repository = repository; - this.tenantService = tenantService; + this.organizationService = organizationService; this.pluginService = pluginService; } @@ -44,17 +44,17 @@ public class ResourceServiceImpl extends BaseService tenantMono = tenantService.findByIdAndPluginsPluginId(tenantId, resource.getPluginId()); + Mono organizationMono = organizationService.findByIdAndPluginsPluginId(organizationId, resource.getPluginId()); - //Add tenant id to the resource. + //Add organization id to the resource. Mono updatedResourceMono = Mono.just(resource) .map(updatedResource -> { - updatedResource.setTenantId(tenantId); + updatedResource.setOrganizationId(organizationId); return updatedResource; }); - return tenantMono - .switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.PLUGIN_NOT_INSTALLED, tenantId))) + return organizationMono + .switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.PLUGIN_NOT_INSTALLED, organizationId))) .then(updatedResourceMono) .flatMap(repository::save); } diff --git a/app/server/src/main/java/com/appsmith/server/services/TenantService.java b/app/server/src/main/java/com/appsmith/server/services/TenantService.java deleted file mode 100644 index 6c8832e174..0000000000 --- a/app/server/src/main/java/com/appsmith/server/services/TenantService.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.appsmith.server.services; - -import com.appsmith.server.domains.Tenant; -import reactor.core.publisher.Mono; - -public interface TenantService extends CrudService { - - Mono getByName(String name); - - Mono create(Tenant object); - - Mono findById(String id); - - Mono save(Tenant tenant); - - Mono findByIdAndPluginsPluginId(String tenantId, String pluginId); -} diff --git a/app/server/src/main/java/com/appsmith/server/services/TenantServiceImpl.java b/app/server/src/main/java/com/appsmith/server/services/TenantServiceImpl.java deleted file mode 100644 index cd7d5a2b95..0000000000 --- a/app/server/src/main/java/com/appsmith/server/services/TenantServiceImpl.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.appsmith.server.services; - -import com.appsmith.server.constants.FieldName; -import com.appsmith.server.domains.Setting; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantSetting; -import com.appsmith.server.exceptions.AppsmithError; -import com.appsmith.server.exceptions.AppsmithException; -import com.appsmith.server.repositories.TenantRepository; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.mongodb.core.ReactiveMongoTemplate; -import org.springframework.data.mongodb.core.convert.MongoConverter; -import org.springframework.stereotype.Service; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.core.scheduler.Scheduler; - -import javax.validation.Validator; -import java.util.ArrayList; -import java.util.List; - -@Slf4j -@Service -public class TenantServiceImpl extends BaseService implements TenantService { - - private final TenantRepository repository; - private final SettingService settingService; - - @Autowired - public TenantServiceImpl(Scheduler scheduler, - Validator validator, - MongoConverter mongoConverter, - ReactiveMongoTemplate reactiveMongoTemplate, - TenantRepository repository, - SettingService settingService) { - super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository); - this.repository = repository; - this.settingService = settingService; - } - - @Override - public Mono getByName(String name) { - return repository.findByName(name); - } - - /* - * Create needs to first fetch and embed Setting in TenantSetting - * for the settings that have diverged from the default. Once the - * settings has been embedded in all the tenant settings, the library - * function is called to store the enhanced tenant object. - */ - @Override - public Mono create(Tenant tenant) { - if (tenant == null) { - return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.TENANT)); - } - - log.debug("Going to create the tenant {}", tenant.getName()); - return Mono.just(tenant) - .flatMap(this::validateObject) - //transform the tenant data to embed setting object in each object in tenantSetting list. - .flatMap(this::enhanceTenantSettingList) - //Call the library function to save the updated tenant - .flatMap(repository::save); - } - - private Mono enhanceTenantSettingList(Tenant tenant) { - - if (tenant.getTenantSettings() == null) { - tenant.setTenantSettings(new ArrayList<>()); - } - - Flux tenantSettingFlux = Flux.fromIterable(tenant.getTenantSettings()); - // For each tenant setting, fetch and embed the setting, and once all the tenant setting are done, collect it - // back into a single list of tenant settings. - Mono> listMono = tenantSettingFlux.flatMap(this::fetchAndEmbedSetting).collectList(); - return listMono.map(list -> { - tenant.setTenantSettings(list); - return list; - }).thenReturn(tenant); - } - - private Mono fetchAndEmbedSetting(TenantSetting tenantSetting) { - - String key = tenantSetting.getSetting().getKey(); - Mono setting = settingService.getByKey(key); - return setting.map(setting1 -> { - tenantSetting.setSetting(setting1); - return tenantSetting; - }); - } - - @Override - public Mono findById(String id) { - return repository.findById(id); - } - - @Override - public Mono save(Tenant tenant) { - return repository.save(tenant); - } - - @Override - public Mono findByIdAndPluginsPluginId(String tenantId, String pluginId) { - return repository.findByIdAndPluginsPluginId(tenantId, pluginId); - } - -} - diff --git a/app/server/src/main/resources/application-local.properties b/app/server/src/main/resources/application-local.properties index c0318a7a2f..a137604007 100644 --- a/app/server/src/main/resources/application-local.properties +++ b/app/server/src/main/resources/application-local.properties @@ -19,5 +19,5 @@ jdbc.postgres.password=root spring.security.oauth2.client.registration.google.client-id=869021686091-9b84bbf7ea683t1aaefqnmefcnmk6fq6.apps.googleusercontent.com spring.security.oauth2.client.registration.google.client-secret=9dvITt4OayEY1HfeY8bHX74p -#Hard coded tenant properties -tenant.id=5d64f1f594a5d31b3ee9ca16 +#Hard coded organization properties +organization.id=5d64f1f594a5d31b3ee9ca16 diff --git a/app/server/src/main/resources/application-staging.properties b/app/server/src/main/resources/application-staging.properties index af5465c038..308607bf98 100644 --- a/app/server/src/main/resources/application-staging.properties +++ b/app/server/src/main/resources/application-staging.properties @@ -17,5 +17,5 @@ jdbc.postgres.password=09275163cd7e737baf4c210b5e8db8ed88ddb7a0ee9acc82416fd7534 spring.security.oauth2.client.registration.google.client-id=869021686091-9b84bbf7ea683t1aaefqnmefcnmk6fq6.apps.googleusercontent.com spring.security.oauth2.client.registration.google.client-secret=9dvITt4OayEY1HfeY8bHX74p -#Hard coded tenant properties -tenant.id=5d3e90a2dfec7c00047a81ea +#Hard coded organization properties +organization.id=5d3e90a2dfec7c00047a81ea diff --git a/app/server/src/main/resources/application.properties b/app/server/src/main/resources/application.properties index b5eec7f76d..e618a2e827 100644 --- a/app/server/src/main/resources/application.properties +++ b/app/server/src/main/resources/application.properties @@ -14,5 +14,5 @@ spring.jpa.show-sql=true # Jackson Properties spring.jackson.default-property-inclusion=non_null -#Hard coded tenant properties -tenant.id=5d5e7c29006cb4e82ea75075 \ No newline at end of file +#Hard coded organization properties +organization.id=5d5e7c29006cb4e82ea75075 \ No newline at end of file diff --git a/app/server/src/test/java/com/appsmith/server/services/OrganizationServiceTest.java b/app/server/src/test/java/com/appsmith/server/services/OrganizationServiceTest.java new file mode 100644 index 0000000000..1813c3a124 --- /dev/null +++ b/app/server/src/test/java/com/appsmith/server/services/OrganizationServiceTest.java @@ -0,0 +1,125 @@ +package com.appsmith.server.services; + +import com.appsmith.server.constants.FieldName; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.exceptions.AppsmithError; +import com.appsmith.server.exceptions.AppsmithException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class OrganizationServiceTest { + + @Autowired + OrganizationService organizationService; + + Organization organization; + + @Before + public void setup() { + organization = new Organization(); + organization.setName("Test Name"); + organization.setDomain("example.com"); + organization.setWebsite("https://example.com"); + } + + /* Tests for the Create Organization Flow */ + + @Test + public void nullCreateOrganization() { + Mono organizationResponse = organizationService.create(null); + StepVerifier.create(organizationResponse) + .expectErrorMatches(throwable -> throwable instanceof AppsmithException && + throwable.getMessage().equals(AppsmithError.INVALID_PARAMETER.getMessage(FieldName.ORGANIZATION))) + .verify(); + } + + @Test + public void nullName() { + organization.setName(null); + Mono organizationResponse = organizationService.create(organization); + StepVerifier.create(organizationResponse) + .expectErrorMatches(throwable -> throwable instanceof AppsmithException && + throwable.getMessage().equals(AppsmithError.INVALID_PARAMETER.getMessage(FieldName.NAME))) + .verify(); + } + + @Test + public void validCreateOrganizationTest() { + Mono organizationResponse = organizationService.create(organization); + StepVerifier.create(organizationResponse) + .assertNext(organization1 -> { + assertThat(organization1.getName()).isEqualTo("Test Name"); + }) + .verifyComplete(); + } + + /* Tests for Get Organization Flow */ + + @Test + public void getOrganizationInvalidId() { + Mono organizationMono = organizationService.getById("random-id"); + StepVerifier.create(organizationMono) + .expectErrorMatches(throwable -> throwable instanceof AppsmithException && + throwable.getMessage().equals(AppsmithError.NO_RESOURCE_FOUND.getMessage("resource", "random-id"))) + .verify(); + } + + @Test + public void getOrganizationNullId() { + Mono organizationMono = organizationService.getById(null); + StepVerifier.create(organizationMono) + .expectErrorMatches(throwable -> throwable instanceof AppsmithException && + throwable.getMessage().equals(AppsmithError.INVALID_PARAMETER.getMessage(FieldName.ID))) + .verify(); + } + + @Test + public void validGetOrganizationByName() { + Mono createOrganization = organizationService.create(organization); + Mono getOrganization = createOrganization.flatMap(t -> organizationService.getById(t.getId())); + StepVerifier.create(getOrganization) + .assertNext(t -> { + assertThat(t).isNotNull(); + assertThat(t.getName()).isEqualTo(organization.getName()); + assertThat(t.getId()).isEqualTo(organization.getId()); + }) + .verifyComplete(); + } + + /* Tests for Update Organization Flow */ + @Test + public void validUpdateOrganization() { + Organization organization = new Organization(); + organization.setName("Test Name"); + organization.setDomain("example.com"); + organization.setWebsite("https://example.com"); + + Mono createOrganization = organizationService.create(organization); + Mono updateOrganization = createOrganization + .map(t -> { + t.setDomain("abc.com"); + return t; + }) + .flatMap(t -> organizationService.update(t.getId(), t)) + .flatMap(t -> organizationService.getById(t.getId())); + + StepVerifier.create(updateOrganization) + .assertNext(t -> { + assertThat(t).isNotNull(); + assertThat(t.getName()).isEqualTo(organization.getName()); + assertThat(t.getId()).isEqualTo(organization.getId()); + assertThat(t.getDomain()).isEqualTo("abc.com"); + }) + .verifyComplete(); + } +} diff --git a/app/server/src/test/java/com/appsmith/server/services/TenantServiceTest.java b/app/server/src/test/java/com/appsmith/server/services/TenantServiceTest.java deleted file mode 100644 index d35a6a5b89..0000000000 --- a/app/server/src/test/java/com/appsmith/server/services/TenantServiceTest.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.appsmith.server.services; - -import com.appsmith.server.constants.FieldName; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.exceptions.AppsmithError; -import com.appsmith.server.exceptions.AppsmithException; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import static org.assertj.core.api.Assertions.assertThat; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class TenantServiceTest { - - @Autowired - TenantService tenantService; - - Tenant tenant; - - @Before - public void setup() { - tenant = new Tenant(); - tenant.setName("Test Name"); - tenant.setDomain("example.com"); - tenant.setWebsite("https://example.com"); - } - - /* Tests for the Create Tenant Flow */ - - @Test - public void nullCreateTenant() { - Mono tenantResponse = tenantService.create(null); - StepVerifier.create(tenantResponse) - .expectErrorMatches(throwable -> throwable instanceof AppsmithException && - throwable.getMessage().equals(AppsmithError.INVALID_PARAMETER.getMessage(FieldName.TENANT))) - .verify(); - } - - @Test - public void nullName() { - tenant.setName(null); - Mono tenantResponse = tenantService.create(tenant); - StepVerifier.create(tenantResponse) - .expectErrorMatches(throwable -> throwable instanceof AppsmithException && - throwable.getMessage().equals(AppsmithError.INVALID_PARAMETER.getMessage(FieldName.NAME))) - .verify(); - } - - @Test - public void validCreateTenantTest() { - Mono tenantResponse = tenantService.create(tenant); - StepVerifier.create(tenantResponse) - .assertNext(tenant1 -> { - assertThat(tenant1.getName()).isEqualTo("Test Name"); - }) - .verifyComplete(); - } - - /* Tests for Get Tenant Flow */ - - @Test - public void getTenantInvalidId() { - Mono tenantMono = tenantService.getById("random-id"); - StepVerifier.create(tenantMono) - .expectErrorMatches(throwable -> throwable instanceof AppsmithException && - throwable.getMessage().equals(AppsmithError.NO_RESOURCE_FOUND.getMessage("resource", "random-id"))) - .verify(); - } - - @Test - public void getTenantNullId() { - Mono tenantMono = tenantService.getById(null); - StepVerifier.create(tenantMono) - .expectErrorMatches(throwable -> throwable instanceof AppsmithException && - throwable.getMessage().equals(AppsmithError.INVALID_PARAMETER.getMessage(FieldName.ID))) - .verify(); - } - - @Test - public void validGetTenantByName() { - Mono createTenant = tenantService.create(tenant); - Mono getTenant = createTenant.flatMap(t -> tenantService.getById(t.getId())); - StepVerifier.create(getTenant) - .assertNext(t -> { - assertThat(t).isNotNull(); - assertThat(t.getName()).isEqualTo(tenant.getName()); - assertThat(t.getId()).isEqualTo(tenant.getId()); - }) - .verifyComplete(); - } - - /* Tests for Update Tenant Flow */ - @Test - public void validUpdateTenant() { - Tenant tenant = new Tenant(); - tenant.setName("Test Name"); - tenant.setDomain("example.com"); - tenant.setWebsite("https://example.com"); - - Mono createTenant = tenantService.create(tenant); - Mono updateTenant = createTenant - .map(t -> { - t.setDomain("abc.com"); - return t; - }) - .flatMap(t -> tenantService.update(t.getId(), t)) - .flatMap(t -> tenantService.getById(t.getId())); - - StepVerifier.create(updateTenant) - .assertNext(t -> { - assertThat(t).isNotNull(); - assertThat(t.getName()).isEqualTo(tenant.getName()); - assertThat(t.getId()).isEqualTo(tenant.getId()); - assertThat(t.getDomain()).isEqualTo("abc.com"); - }) - .verifyComplete(); - } -}