Move application configuration to be loaded from environment variables (#23)

* Move application configuration to be loaded from environment variables
* Remove unused sentry.properties
* Make missing value sentinel a constant and ignore all *.env files
* Removed now-used ACL properties
* Prefix RapidAPI environment variable with APPSMITH_
* Fix application properties not being loaded into static fields
* Remove application-test.properties file
* Add required env variables for test in GitHub
* Quote URLs for MongoDB and Redis in test config
* Change RAPIDAPI to RAPID_API in environment variable names
* Source .env file in the root of repo in start script
This commit is contained in:
Shrikant Sharat Kandula 2020-07-06 14:35:56 +05:30 committed by GitHub
parent 1e67ea21c0
commit 56547ec02f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 223 additions and 439 deletions

View File

@ -1,5 +1,5 @@
# This workflow is responsible for building, testing & packaging the Java server codebase
name: Appsmith Server Workflow
name: Appsmith Server Workflow
on:
push:
@ -29,11 +29,11 @@ jobs:
ports:
# Opens tcp port 6379 on the host and service container
- 6379:6379
steps:
# Checkout the code
- uses: actions/checkout@v2
# Setup Java
- name: Set up JDK 1.11
uses: actions/setup-java@v1
@ -54,28 +54,29 @@ jobs:
# Build and test the code
- name: Build and test
env:
SPRING_PROFILES_ACTIVE: test
run: mvn -B package -Dspring.profiles.active=$SPRING_PROFILES_ACTIVE
# Here, the GITHUB_REF is of type /refs/head/<branch_name>. We extract branch_name from this by removing the
APPSMITH_MONGODB_URI: "mongodb://localhost:27017/mobtools"
APPSMITH_REDIS_URL: "redis://127.0.0.1:6379"
run: mvn -B package
# Here, the GITHUB_REF is of type /refs/head/<branch_name>. We extract branch_name from this by removing the
# first 11 characters. This can be used to build images for several branches
- name: Get the version to tag the Docker image
id: vars
run: echo ::set-output name=tag::$(echo ${GITHUB_REF:11})
# Build release Docker image and push to Docker Hub
- name: Push release image to Docker Hub
if: success() && github.ref == 'refs/heads/release'
run: |
docker build -t appsmith/test-appsmith-repo:${{steps.vars.outputs.tag}} .
docker build -t appsmith/appsmith-server:${{steps.vars.outputs.tag}} .
echo ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin
docker push appsmith/test-appsmith-repo
docker push appsmith/appsmith-server
# Build master Docker image and push to Docker Hub
- name: Push master image to Docker Hub with commit tag
if: success() && github.ref == 'refs/heads/master'
run: |
docker build -t appsmith/test-appsmith-repo:${GITHUB_SHA} .
docker build -t appsmith/test-appsmith-repo:latest .
docker build -t appsmith/appsmith-server:${GITHUB_SHA} .
docker build -t appsmith/appsmith-server:latest .
echo ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin
docker push appsmith/test-appsmith-repo
docker push appsmith/appsmith-server

View File

@ -11,4 +11,5 @@ node_modules
**/.settings
**/.classpath
**/.project
**/.factorypath
**/.factorypath
*.env

View File

@ -15,10 +15,12 @@ import org.bson.internal.Base64;
import org.json.JSONObject;
import org.pf4j.Extension;
import org.pf4j.PluginWrapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
@ -40,8 +42,7 @@ import java.util.regex.Pattern;
public class RapidApiPlugin extends BasePlugin {
private static final int MAX_REDIRECTS = 5;
private static final String RAPID_API_KEY_NAME = "X-RapidAPI-Key";
private static final String RAPID_API_KEY_VALUE = "6d804a25b8mshc11f75089009c26p12c8d8jsna1a83b13ffd5";
private static final String JSON_TYPE = "apipayload";
public RapidApiPlugin(PluginWrapper wrapper) {
@ -52,11 +53,21 @@ public class RapidApiPlugin extends BasePlugin {
@Extension
public static class RapidApiPluginExecutor implements PluginExecutor {
@Value("${rapidapi.key.name}")
private String rapidApiKeyName;
@Value("${rapidapi.key.value}")
private String rapidApiKeyValue;
@Override
public Mono<Object> execute(Object connection,
DatasourceConfiguration datasourceConfiguration,
ActionConfiguration actionConfiguration) {
if (StringUtils.isEmpty(rapidApiKeyValue)) {
return Mono.error(new AppsmithPluginException(AppsmithPluginError.PLUGIN_ERROR, "RapidAPI Key value not set."));
}
String requestBody = (actionConfiguration.getBody() == null) ? "" : actionConfiguration.getBody();
String path = (actionConfiguration.getPath() == null) ? "" : actionConfiguration.getPath();
String url = datasourceConfiguration.getUrl() + path;
@ -77,7 +88,7 @@ public class RapidApiPlugin extends BasePlugin {
}
// Add the rapid api headers
webClientBuilder.defaultHeader(RAPID_API_KEY_NAME, RAPID_API_KEY_VALUE);
webClientBuilder.defaultHeader(rapidApiKeyName, rapidApiKeyValue);
//If route parameters exist, update the URL by replacing the key surrounded by '{' and '}'
if (actionConfiguration.getRouteParameters() != null && !actionConfiguration.getRouteParameters().isEmpty()) {
@ -258,7 +269,9 @@ public class RapidApiPlugin extends BasePlugin {
@Override
public Mono<DatasourceTestResult> testDatasource(DatasourceConfiguration datasourceConfiguration) {
return Mono.just(new DatasourceTestResult());
return StringUtils.isEmpty(rapidApiKeyValue)
? Mono.error(new AppsmithPluginException(AppsmithPluginError.PLUGIN_ERROR, "RapidAPI Key value not set."))
: Mono.just(new DatasourceTestResult());
}
private void addHeadersToRequest(WebClient.Builder webClientBuilder, List<Property> headers) {

View File

@ -1,86 +0,0 @@
package com.appsmith.server.acl;
import com.appsmith.server.configurations.AclConfig;
import com.appsmith.server.domains.User;
import com.appsmith.server.services.GroupService;
import com.appsmith.server.services.SessionUserService;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.util.HashSet;
import java.util.Set;
@Slf4j
@Component
public class AclService {
private final String url;
private final String pkgName;
private final SessionUserService sessionUserService;
private final GroupService groupService;
@Autowired
public AclService(
AclConfig aclConfig,
SessionUserService sessionUserService,
GroupService groupService) {
this.url = aclConfig.getHost();
this.pkgName = aclConfig.getPkgName();
this.sessionUserService = sessionUserService;
this.groupService = groupService;
}
public Mono<OpaResponse> evaluateAcl(HttpMethod httpMethod, String resource, String requestUrl) {
JSONObject requestBody = new JSONObject();
JSONObject input = new JSONObject();
JSONObject jsonUser = new JSONObject();
input.put("user", jsonUser);
input.put("method", httpMethod.name());
input.put("resource", resource);
input.put("url", requestUrl); // The url is required for OPA to gate keep only public URLs for anonymous users
requestBody.put("input", input);
Mono<User> user = sessionUserService.getCurrentUser();
return user
// This is when the user doesn't have an existing session. The user is anonymous
.switchIfEmpty(Mono.defer(() -> {
User anonymous = new User();
return Mono.just(anonymous);
}))
.flatMap(u -> {
Set<String> globalPermissions = new HashSet<>();
Set<String> groupSet = u.getGroupIds();
globalPermissions.addAll(u.getPermissions());
return groupService.getAllById(groupSet)
.map(group -> group.getPermissions())
.map(permissions -> globalPermissions.addAll(permissions))
.collectList()
.thenReturn(globalPermissions);
})
.flatMap(permissions -> {
jsonUser.put("permissions", permissions);
String finalUrl = url + pkgName;
log.debug("Going to make a data call to OPA: {} with data {}", url, requestBody);
WebClient webClient = WebClient.builder()
.baseUrl(finalUrl)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build();
WebClient.RequestHeadersSpec<?> request = webClient.post().bodyValue(requestBody.toString());
return request.retrieve().bodyToMono(OpaResponse.class);
});
}
}

View File

@ -2,6 +2,8 @@ package com.appsmith.server.authentication.handlers;
import com.appsmith.server.configurations.CommonConfig;
import com.appsmith.server.constants.Security;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@ -68,6 +70,8 @@ public class CustomServerOAuth2AuthorizationRequestResolver implements ServerOAu
private final StringKeyGenerator secureKeyGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96);
private static final String MISSING_VALUE_SENTINEL = "missing_value_sentinel";
private final CommonConfig commonConfig;
/**
@ -111,7 +115,13 @@ public class CustomServerOAuth2AuthorizationRequestResolver implements ServerOAu
public Mono<OAuth2AuthorizationRequest> resolve(ServerWebExchange exchange,
String clientRegistrationId) {
return this.findByRegistrationId(exchange, clientRegistrationId)
.map(clientRegistration -> authorizationRequest(exchange, clientRegistration));
.flatMap(clientRegistration -> {
if (MISSING_VALUE_SENTINEL.equals(clientRegistration.getClientId())) {
return Mono.error(new AppsmithException(AppsmithError.OAUTH_NOT_AVAILABLE, clientRegistrationId));
} else {
return Mono.just(authorizationRequest(exchange, clientRegistration));
}
});
}
private Mono<ClientRegistration> findByRegistrationId(ServerWebExchange exchange, String clientRegistration) {

View File

@ -1,17 +0,0 @@
package com.appsmith.server.configurations;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Configuration
@Getter
public class AclConfig {
@Value("${acl.host}")
String host;
@Value("${acl.package.name}")
String pkgName;
}

View File

@ -8,27 +8,27 @@ import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@Getter
@Setter
@Configuration
public class CommonConfig {
private String ELASTIC_THREAD_POOL_NAME = "appsmith-elastic-pool";
private static final String ELASTIC_THREAD_POOL_NAME = "appsmith-elastic-pool";
@Value("${oauth2.allowed-domains:}")
@Value("${oauth2.allowed-domains}")
private String allowedDomainList;
List<String> domainList;
private List<String> domainList;
@Bean
public Scheduler scheduler() {
@ -49,17 +49,12 @@ public class CommonConfig {
}
public List<String> getAllowedDomains() {
if (allowedDomainList == null || allowedDomainList.trim().isEmpty()) {
return new ArrayList<>();
if (domainList == null) {
domainList = StringUtils.hasText(allowedDomainList)
? Arrays.asList(allowedDomainList.trim().split("\\s*,[,\\s]*"))
: Collections.emptyList();
}
if (this.domainList == null) {
this.domainList = Arrays.asList(allowedDomainList.split(","))
.stream()
.filter(domain -> (domain != null && !domain.trim().isEmpty()))
.collect(Collectors.toList());
}
return this.domainList;
return domainList;
}
}

View File

@ -8,5 +8,5 @@ import org.springframework.context.annotation.Configuration;
@Getter
public class MarketplaceConfig {
@Value("${marketplace.base-url}")
String base_url;
String baseUrl;
}

View File

@ -1,8 +1,9 @@
package com.appsmith.server.configurations;
import com.rollbar.notifier.Rollbar;
import org.springframework.beans.factory.annotation.Autowired;
import com.rollbar.notifier.config.ConfigBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
@ -10,24 +11,35 @@ import org.springframework.core.env.Environment;
import static com.rollbar.notifier.config.ConfigBuilder.withAccessToken;
@Configuration
@ConditionalOnExpression(value="!'${com.rollbar.access-token:}'.isEmpty()")
public class RollbarConfig {
@Value("${com.rollbar.access-token}")
String rollbarAccessToken;
private String rollbarAccessToken;
// Allow being able to disable Rollbar in dev/test environments.
// If the `rollbar.enabled` property is not set, it defaults to `true` (by the `:true` part below).
@Value("#{new Boolean('${rollbar.enabled:true}'.trim())}")
boolean rollbarEnabled;
@Value("${rollbar.env:}")
private String rollbarEnv;
@Autowired
Environment env;
final Environment env;
public RollbarConfig(Environment env) {
this.env = env;
}
@Bean
Rollbar rollbarConfiguration() {
return Rollbar.init(withAccessToken(rollbarAccessToken)
.enabled(rollbarEnabled)
.environment(env.getActiveProfiles()[0])
.build());
// The Rollbar env, if not set, defaults to being the first Spring profile.
String environment = rollbarEnv;
if ((environment == null || environment.isEmpty()) && env.getActiveProfiles().length > 0) {
environment = env.getActiveProfiles()[0];
}
ConfigBuilder builder = withAccessToken(rollbarAccessToken);
if (environment != null) {
builder = builder.environment(environment);
}
return Rollbar.init(builder.build());
}
}

View File

@ -2,11 +2,14 @@ package com.appsmith.server.configurations;
import com.segment.analytics.Analytics;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnExpression(value="!'${segment.writeKey:}'.isEmpty()")
public class SegmentConfig {
@Value("${segment.writeKey}")
private String writeKey;
@ -14,4 +17,5 @@ public class SegmentConfig {
public Analytics analyticsRunner() {
return Analytics.builder(writeKey).build();
}
}

View File

@ -49,6 +49,8 @@ public enum AppsmithError {
DATASOURCE_HAS_ACTIONS(409, 4030, "Cannot delete datasource since it has {0} action(s) using it."),
ORGANIZATION_ID_NOT_GIVEN(400, 4031, "Missing organization id. Please enter one."),
INVALID_CURL_METHOD(400, 4032, "Invalid method in cURL command: {0}."),
OAUTH_NOT_AVAILABLE(500, 5006, "Login with {0} is not supported."),
MARKETPLACE_NOT_CONFIGURED(500, 5007, "Marketplace is not configured."),
;

View File

@ -3,7 +3,6 @@ package com.appsmith.server.exceptions;
import com.appsmith.external.pluginExceptions.AppsmithPluginException;
import com.appsmith.server.dtos.ResponseDTO;
import com.rollbar.notifier.Rollbar;
import com.segment.analytics.Analytics;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
@ -23,15 +22,21 @@ import reactor.core.publisher.Mono;
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
private final Analytics analytics;
private final Rollbar rollbar;
@Autowired
public GlobalExceptionHandler(Analytics analytics, Rollbar rollbar) {
this.analytics = analytics;
public GlobalExceptionHandler(@Autowired(required = false) Rollbar rollbar) {
this.rollbar = rollbar;
}
private void doLog(Throwable error) {
log.error("", error);
if (rollbar != null) {
rollbar.log(error);
}
}
/**
* 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
@ -45,8 +50,7 @@ public class GlobalExceptionHandler {
@ResponseBody
public Mono<ResponseDTO<ErrorDTO>> catchAppsmithException(AppsmithException e, ServerWebExchange exchange) {
exchange.getResponse().setStatusCode(HttpStatus.resolve(e.getHttpStatus()));
log.error("", e);
rollbar.log(e);
doLog(e);
return Mono.just(new ResponseDTO<>(e.getHttpStatus(), new ErrorDTO(e.getAppErrorCode(), e.getMessage())));
}
@ -55,8 +59,7 @@ public class GlobalExceptionHandler {
public Mono<ResponseDTO<ErrorDTO>> catchDuplicateKeyException(org.springframework.dao.DuplicateKeyException e, ServerWebExchange exchange) {
AppsmithError appsmithError = AppsmithError.DUPLICATE_KEY;
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
log.error("", e);
rollbar.log(e);
doLog(e);
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
appsmithError.getMessage(e.getMessage()))));
}
@ -66,8 +69,7 @@ public class GlobalExceptionHandler {
public Mono<ResponseDTO<ErrorDTO>> catchTimeoutException(java.util.concurrent.TimeoutException e, ServerWebExchange exchange) {
AppsmithError appsmithError = AppsmithError.PLUGIN_EXECUTION_TIMEOUT;
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
log.error("", e);
rollbar.log(e);
doLog(e);
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
appsmithError.getMessage())));
}
@ -77,8 +79,7 @@ public class GlobalExceptionHandler {
public Mono<ResponseDTO<ErrorDTO>> catchServerWebInputException(ServerWebInputException e, ServerWebExchange exchange) {
AppsmithError appsmithError = AppsmithError.GENERIC_BAD_REQUEST;
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
log.error("", e);
rollbar.log(e);
doLog(e);
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
appsmithError.getMessage(e.getReason()))));
}
@ -88,8 +89,7 @@ public class GlobalExceptionHandler {
public Mono<ResponseDTO<ErrorDTO>> catchPluginException(AppsmithPluginException e, ServerWebExchange exchange) {
AppsmithError appsmithError = AppsmithError.INTERNAL_SERVER_ERROR;
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
log.error("", e);
rollbar.log(e);
doLog(e);
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
e.getLocalizedMessage())));
}
@ -99,8 +99,7 @@ public class GlobalExceptionHandler {
public Mono<ResponseDTO<ErrorDTO>> catchAccessDeniedException(AccessDeniedException e, ServerWebExchange exchange) {
AppsmithError appsmithError = AppsmithError.UNAUTHORIZED_ACCESS;
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
log.error("", e);
rollbar.log(e);
doLog(e);
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
appsmithError.getMessage())));
}
@ -118,8 +117,7 @@ public class GlobalExceptionHandler {
public Mono<ResponseDTO<ErrorDTO>> catchException(Exception e, ServerWebExchange exchange) {
AppsmithError appsmithError = AppsmithError.INTERNAL_SERVER_ERROR;
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
log.error("", e);
rollbar.log(e);
doLog(e);
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
appsmithError.getMessage())));
}

View File

@ -1,75 +0,0 @@
package com.appsmith.server.filters;
import com.appsmith.server.acl.AclService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
@Component
@Slf4j
public class AclFilter implements WebFilter {
final AclService aclService;
final ObjectMapper objectMapper;
@Autowired
public AclFilter(AclService aclService, ObjectMapper objectMapper) {
this.aclService = aclService;
this.objectMapper = objectMapper;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange);
// ServerHttpRequest request = exchange.getRequest();
// HttpMethod httpMethod = request.getMethod();
// String url = request.getPath().value();
// String[] urlParts = url.split("/");
//
// // This is because all the urls are of the form /api/v1/{resource}. When we split by "/", the resource is always
// // the 4th element in the result array
// if (urlParts.length < 4) {
// log.debug("Got request path {}. Not applying ACL filter", request.getPath());
// return chain.filter(exchange);
// }
//
// String resource = urlParts[3];
//
// Mono<OpaResponse> aclResponse = aclService.evaluateAcl(httpMethod, resource, url);
// return aclResponse
// .map(acl -> {
// log.debug("Got ACL response: {}", acl);
// return acl;
// })
// .flatMap(acl -> {
// if (acl != null && acl.isSuccessful()) {
// // Acl returned true. Continue with the filter chain
// return chain.filter(exchange);
// }
//
// // The Acl response is false. Return unauthorized exception to the client
// // We construct the error response JSON here because throwing an exception here doesn't get caught
// // in the {@see GlobalExceptionHandler}.
// AppsmithError error = AppsmithError.UNAUTHORIZED_ACCESS;
// exchange.getResponse().setStatusCode(HttpStatus.resolve(error.getHttpErrorCode()));
// exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
// try {
// ResponseDTO<ErrorDTO> responseBody = new ResponseDTO<>(error.getHttpErrorCode(), new ErrorDTO(error.getAppErrorCode(),
// error.getMessage()));
// String responseStr = objectMapper.writeValueAsString(responseBody);
// DataBuffer buffer = exchange.getResponse().bufferFactory().allocateBuffer().write(responseStr.getBytes());
// return exchange.getResponse().writeWith(Mono.just(buffer));
// } catch (JsonProcessingException e) {
// log.error("Exception caught while serializing JSON in AclFilter. Cause: ", e);
// return exchange.getResponse().writeWith(Mono.empty());
// }
// });
}
}

View File

@ -21,12 +21,16 @@ public class AnalyticsService<T extends BaseDomain> {
private final SessionUserService sessionUserService;
@Autowired
public AnalyticsService(Analytics analytics, SessionUserService sessionUserService) {
public AnalyticsService(@Autowired(required = false) Analytics analytics, SessionUserService sessionUserService) {
this.analytics = analytics;
this.sessionUserService = sessionUserService;
}
public Mono<User> trackNewUser(User user) {
if (analytics == null) {
return Mono.just(user);
}
return Mono.just(user)
.map(savedUser -> {
Map<String, String> traitsMap = new HashMap<>();
@ -44,6 +48,10 @@ public class AnalyticsService<T extends BaseDomain> {
}
public Mono<T> sendEvent(String eventTag, T object) {
if (analytics == null) {
return Mono.just(object);
}
// We will create an anonymous user object for event tracking if no user is present
// Without this, a lot of flows meant for anonymous users will error out
Mono<User> userMono = sessionUserService.getCurrentUser();

View File

@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
@ -54,7 +55,7 @@ public class MarketplaceServiceImpl implements MarketplaceService {
this.marketplaceConfig = marketplaceConfig;
this.webClient = webClientBuilder
.defaultHeaders(header -> header.setBasicAuth(MARKETPLACE_USERNAME, MARKETPLACE_PASSWORD))
.baseUrl(marketplaceConfig.getBase_url())
.baseUrl(marketplaceConfig.getBaseUrl())
.build();
this.objectMapper = objectMapper;
}
@ -63,6 +64,10 @@ public class MarketplaceServiceImpl implements MarketplaceService {
public Mono<ProviderPaginatedDTO> getProviders(MultiValueMap<String, String> params) {
URI uri = buildFullURI(params, PROVIDER_PATH);
if (uri == null) {
return Mono.error(new AppsmithException(AppsmithError.MARKETPLACE_NOT_CONFIGURED));
}
return webClient
.get()
.uri(uri)
@ -85,6 +90,10 @@ public class MarketplaceServiceImpl implements MarketplaceService {
public Mono<List<ApiTemplate>> getTemplates(MultiValueMap<String, String> params) {
URI uri = buildFullURI(params, TEMPLATE_PATH);
if (uri == null) {
return Mono.error(new AppsmithException(AppsmithError.MARKETPLACE_NOT_CONFIGURED));
}
return webClient
.get()
.uri(uri)
@ -107,6 +116,10 @@ public class MarketplaceServiceImpl implements MarketplaceService {
public Mono<List<String>> getCategories() {
URI uri = buildFullURI(null, CATEGORIES_PATH);
if (uri == null) {
return Mono.error(new AppsmithException(AppsmithError.MARKETPLACE_NOT_CONFIGURED));
}
return webClient
.get()
.uri(uri)
@ -132,8 +145,7 @@ public class MarketplaceServiceImpl implements MarketplaceService {
URI uri = buildFullURI(params, USE_PROVIDER_API);
if (uri == null) {
// Throw an internal server error because the URL is hard coded and must be correct
return Mono.error(new AppsmithException(AppsmithError.INTERNAL_SERVER_ERROR));
return Mono.error(new AppsmithException(AppsmithError.MARKETPLACE_NOT_CONFIGURED));
}
return webClient
@ -147,6 +159,10 @@ public class MarketplaceServiceImpl implements MarketplaceService {
public Mono<Provider> getProviderById(String id) {
URI uri = buildFullURI(null, PROVIDER_PATH + "/" + id);
if (uri == null) {
return Mono.error(new AppsmithException(AppsmithError.MARKETPLACE_NOT_CONFIGURED));
}
return webClient
.get()
.uri(uri)
@ -174,6 +190,10 @@ public class MarketplaceServiceImpl implements MarketplaceService {
public Mono<List<Provider>> searchProviderByName(String name) {
URI uri = buildFullURI(null, PROVIDER_PATH + "/name/" + URLEncoder.encode(name, StandardCharsets.UTF_8));
if (uri == null) {
return Mono.error(new AppsmithException(AppsmithError.MARKETPLACE_NOT_CONFIGURED));
}
return webClient
.get()
.uri(uri)
@ -193,9 +213,14 @@ public class MarketplaceServiceImpl implements MarketplaceService {
}
private URI buildFullURI(MultiValueMap<String, String> params, String path) {
final String baseUrl = marketplaceConfig.getBaseUrl();
if (!StringUtils.hasText(baseUrl)) {
return null;
}
UriComponentsBuilder uriBuilder = UriComponentsBuilder.newInstance();
try {
uriBuilder.uri(new URI(marketplaceConfig.getBase_url() + path));
uriBuilder.uri(new URI(baseUrl + path));
} catch (URISyntaxException e) {
log.error(e.getMessage());
return null;

View File

@ -1,50 +0,0 @@
# Appsmith Configurations
appsmith.baseUri=http://localhost:8080
#Mongo properties
spring.data.mongodb.database=mobtools
spring.data.mongodb.host=mongo
spring.data.mongodb.port=27017
#spring.data.mongodb.username=
#spring.data.mongodb.password=
marketplace.base-url = http://localhost:8081/api/v1
# Log properties
logging.level.root=info
logging.level.com.appsmith=debug
logging.pattern.console=%X - %m%n
#Spring security
spring.security.oauth2.client.registration.google.client-id=869021686091-9b84bbf7ea683t1aaefqnmefcnmk6fq6.apps.googleusercontent.com
spring.security.oauth2.client.registration.google.client-secret=9dvITt4OayEY1HfeY8bHX74p
spring.security.oauth2.client.provider.google.userNameAttribute=email
spring.security.oauth2.client.registration.github.client-id=ffa2f7468ea72758871c
spring.security.oauth2.client.registration.github.client-secret=b9c81a1a3216328b55a7df2d49fe2bbb6b1070f1
spring.security.oauth2.client.provider.github.userNameAttribute=login
# Accounts from specific domains are allowed to login
oauth2.allowed-domains=
# Segment & Rollbar Properties
# These properties are intentionally set to random values so that events are not sent to either of them during local development
segment.writeKey=random-value
com.rollbar.access-token=random-value
# Redis Properties
spring.redis.host=redis
spring.redis.port=6379
# ACL config parameters
acl.host=http://opa:8181/v1/data
acl.package.name=/appsmith/authz/url_allow
# Mail Properties
mail.enabled=true
spring.mail.host=email-smtp.us-east-1.amazonaws.com
spring.mail.port=587
spring.mail.username=AKIAVWHAAGIQOHPT4BZ7
spring.mail.password=BEE5W6i7YznAJ/YDOLbppovmOlRzxXElJ+uJtGhdCfjY
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

View File

@ -1,42 +0,0 @@
# Appsmith Configurations
appsmith.baseUri=http://localhost:8080
spring.main.allow-bean-definition-overriding=true
#Mongo properties
spring.data.mongodb.database=mobtools
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
#spring.data.mongodb.username=
#spring.data.mongodb.password=
marketplace.base-url=http://localhost:8081/api/v1
# Log properties
logging.level.root=info
logging.level.com.appsmith=debug
logging.pattern.console=%X - %m%n
#Spring security
spring.security.oauth2.client.registration.google.client-id=869021686091-9b84bbf7ea683t1aaefqnmefcnmk6fq6.apps.googleusercontent.com
spring.security.oauth2.client.registration.google.client-secret=9dvITt4OayEY1HfeY8bHX74p
spring.security.oauth2.client.provider.google.userNameAttribute=email
spring.security.oauth2.client.registration.github.client-id=13b4739f879d16371e2f
spring.security.oauth2.client.registration.github.client-secret=ceb5052bda7d759e35b449efe333a25dcaa601cc
spring.security.oauth2.client.provider.github.userNameAttribute=login
# Accounts from specific domains are allowed to login
#oauth2.allowed-domains=appsmith.com
# Segment & Rollbar Properties
# These properties are intentionally set to random values so that events are not sent to either of them during local development
segment.writeKey=random-value
com.rollbar.access-token=random-value
rollbar.enabled=false
# Redis Properties
spring.redis.host=127.0.0.1
spring.redis.port=6379
# ACL config parameters
acl.host=http://localhost:8181/v1/data
acl.package.name=/appsmith/authz/url_allow
# Mail Properties
mail.enabled=false
spring.mail.host=email-smtp.us-east-1.amazonaws.com
spring.mail.port=587
spring.mail.username=AKIAVWHAAGIQOHPT4BZ7
spring.mail.password=BEE5W6i7YznAJ/YDOLbppovmOlRzxXElJ+uJtGhdCfjY
spring.mail.properties.mail.smtp.auth=false
spring.mail.properties.mail.smtp.starttls.enable=true

View File

@ -1,49 +0,0 @@
# Appsmith Configurations
appsmith.baseUri=https://release-api.appsmith.com
#Mongo properties
spring.data.mongodb.database=mobtools
spring.data.mongodb.uri=mongodb+srv://admin:Y9PuxM52gcP3Dgfo@mobtools-test-cluster-swrsq.mongodb.net/mobtools?retryWrites=true&minPoolSize=1&maxPoolSize=10&maxIdleTimeMS=900000
spring.data.mongodb.authentication-database=admin
marketplace.base-url = https://release-marketplace.appsmith.com/api/v1
# Log properties
logging.level.root=info
logging.level.com.appsmith=debug
logging.pattern.console=%X - %m%n
#Spring security
spring.security.oauth2.client.registration.google.client-id=869021686091-9b84bbf7ea683t1aaefqnmefcnmk6fq6.apps.googleusercontent.com
spring.security.oauth2.client.registration.google.client-secret=9dvITt4OayEY1HfeY8bHX74p
spring.security.oauth2.client.provider.google.userNameAttribute=email
spring.security.oauth2.client.registration.github.client-id=cfc2abddcddef0da42d1
spring.security.oauth2.client.registration.github.client-secret=b02322188812dfce0b65ba329e242f231121d7b0
spring.security.oauth2.client.provider.github.userNameAttribute=login
# Accounts from specific domains are allowed to login
oauth2.allowed-domains=
# Segment & Rollbar Properties
segment.writeKey=B3UBOacfOky4l6dfk5xyR6Dh8vUZYizW
com.rollbar.access-token=b91c4d5b9cac444088f4db9216ed6f42
# Redis Properties
spring.redis.host=ec2-34-254-16-19.eu-west-1.compute.amazonaws.com
spring.redis.port=18689
spring.redis.user=h
spring.redis.password=p46c3e6d77c32e6f1026f16ae781911d8a2631ece413406a75fc31b0cfb9edb03
# ACL config parameters
acl.host=https://openpolicyagent.herokuapp.com/v1/data
acl.package.name=/appsmith/authz/url_allow
# Mail Properties
mail.enabled=true
spring.mail.host=email-smtp.us-east-1.amazonaws.com
spring.mail.port=587
spring.mail.username=AKIAVWHAAGIQOHPT4BZ7
spring.mail.password=BEE5W6i7YznAJ/YDOLbppovmOlRzxXElJ+uJtGhdCfjY
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

View File

@ -5,3 +5,49 @@ spring.data.mongodb.auto-index-creation=false
# Ensures that the size of the request object that we handle is controlled. By default it's 212KB.
spring.codec.max-in-memory-size=5MB
# MongoDB Application Database
spring.data.mongodb.uri = ${APPSMITH_MONGODB_URI}
marketplace.base-url = ${APPSMITH_MARKETPLACE_URL:}
# Log properties
logging.level.root=info
logging.level.com.appsmith=debug
logging.pattern.console=%X - %m%n
#Spring security
spring.security.oauth2.client.registration.google.client-id=${APPSMITH_OAUTH2_GOOGLE_CLIENT_ID:missing_value_sentinel}
spring.security.oauth2.client.registration.google.client-secret=${APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET:}
spring.security.oauth2.client.provider.google.userNameAttribute=email
spring.security.oauth2.client.registration.github.client-id=${APPSMITH_OAUTH2_GITHUB_CLIENT_ID:missing_value_sentinel}
spring.security.oauth2.client.registration.github.client-secret=${APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET:}
spring.security.oauth2.client.provider.github.userNameAttribute=login
# Accounts from specific domains are allowed to login
oauth2.allowed-domains=${APPSMITH_OAUTH2_ALLOWED_DOMAINS:}
# Segment & Rollbar Properties
# These properties are intentionally set to random values so that events are not sent to either of them during local development
segment.writeKey=${APPSMITH_SEGMENT_KEY:}
com.rollbar.access-token=${APPSMITH_ROLLBAR_ACCESS_TOKEN:}
roolbar.env = ${APPSMITH_ROLLBAR_ENV:}
# RapidAPI
rapidapi.key.name = X-RapidAPI-Key
rapidapi.key.value = ${APPSMITH_RAPID_API_KEY_VALUE:}
# Redis Properties
spring.redis.url=${APPSMITH_REDIS_URL}
# Mail Properties
# Email defaults to false, because, when true and the other SMTP properties are not set, Spring will try to use a
# default localhost:25 SMTP server and throw an error. If false, this error won't happen because there's no attempt
# to send an email.
mail.enabled=${APPSMITH_MAIL_ENABLED:false}
spring.mail.host=${APPSMITH_MAIL_HOST:}
spring.mail.port=${APPSMITH_MAIL_PORT:}
spring.mail.username=${APPSMITH_MAIL_USERNAME:}
spring.mail.password=${APPSMITH_MAIL_PASSWORD:}
spring.mail.properties.mail.smtp.auth=${APPSMITH_MAIL_SMTP_AUTH:}
spring.mail.properties.mail.smtp.starttls.enable=${APPSMITH_MAIL_SMTP_TLS_ENABLED:}

View File

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

View File

@ -1,44 +0,0 @@
#Mongo properties
spring.data.mongodb.database=mobtools
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
#spring.data.mongodb.username=
#spring.data.mongodb.password=
marketplace.base-url = http://localhost:8081/api/v1
# Log properties
logging.level.root=error
logging.level.com.appsmith=debug
logging.pattern.console=%X - %m%n
#Spring security
spring.security.oauth2.client.registration.google.client-id=869021686091-9b84bbf7ea683t1aaefqnmefcnmk6fq6.apps.googleusercontent.com
spring.security.oauth2.client.registration.google.client-secret=9dvITt4OayEY1HfeY8bHX74p
# Accounts from specific domains are allowed to login
oauth2.allowed-domains=appsmith.com
# Segment & Rollbar Properties
# These properties are intentionally set to random values so that events are not sent to either of them during local development
segment.writeKey=random-value
com.rollbar.access-token=random-value
com.rollbar.environment=development
# Redis Properties
spring.redis.host=localhost
spring.redis.port=6379
# ACL config parameters
acl.host=http://opa:8181/v1/data
acl.package.name=/appsmith/authz/url_allow
# Mail Properties
mail.enabled=false
spring.mail.host=email-smtp.us-east-1.amazonaws.com
spring.mail.port=587
spring.mail.username=AKIAVWHAAGIQOHPT4BZ7
spring.mail.password=BEE5W6i7YznAJ/YDOLbppovmOlRzxXElJ+uJtGhdCfjY
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

View File

@ -3,8 +3,10 @@ version: "3.7"
services:
appsmith-internal-server:
image: arpitappsmith/appsmith-server:maven
env_file: envs/docker.env
environment:
- SPRING_PROFILES_ACTIVE=docker
APPSMITH_MONGODB_URI: "mongodb://mongo:27017/mobtools"
APPSMITH_REDIS_URL: "redis://redis:6379"
ports:
- "8080:8080"
links:

View File

@ -0,0 +1,5 @@
#!/bin/sh
APPSMITH_MONGODB_URI="mongodb://localhost:27017/mobtools"
APPSMITH_REDIS_URL="redis://127.0.0.1:6379"

View File

@ -0,0 +1,16 @@
#!/bin/sh
APPSMITH_OAUTH2_GOOGLE_CLIENT_ID=""
APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET=""
APPSMITH_OAUTH2_GITHUB_CLIENT_ID=""
APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET=""
APPSMITH_RAPID_API_KEY_VALUE=""
APPSMITH_MAIL_ENABLED=true
APPSMITH_MAIL_HOST=localhost
APPSMITH_MAIL_PORT=25
APPSMITH_MAIL_USERNAME=
APPSMITH_MAIL_PASSWORD=
APPSMITH_MAIL_SMTP_AUTH=true
APPSMITH_MAIL_SMTP_TLS_ENABLED=true

View File

@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Change to the parent directory of the directory containing this script.
cd "$(cd "$(dirname "$0")" && pwd)/.."
# Ref: <https://stackoverflow.com/a/30969768/151048>.
if [[ -f .env ]]; then
echo "Found a .env file, loading environment variables from that file."
set -o allexport
source .env
fi
exec java -jar dist/server-*.jar