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:
parent
1e67ea21c0
commit
56547ec02f
15
.github/workflows/server.yml
vendored
15
.github/workflows/server.yml
vendored
|
|
@ -54,8 +54,9 @@ jobs:
|
||||||
# Build and test the code
|
# Build and test the code
|
||||||
- name: Build and test
|
- name: Build and test
|
||||||
env:
|
env:
|
||||||
SPRING_PROFILES_ACTIVE: test
|
APPSMITH_MONGODB_URI: "mongodb://localhost:27017/mobtools"
|
||||||
run: mvn -B package -Dspring.profiles.active=$SPRING_PROFILES_ACTIVE
|
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
|
# 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
|
# first 11 characters. This can be used to build images for several branches
|
||||||
|
|
@ -67,15 +68,15 @@ jobs:
|
||||||
- name: Push release image to Docker Hub
|
- name: Push release image to Docker Hub
|
||||||
if: success() && github.ref == 'refs/heads/release'
|
if: success() && github.ref == 'refs/heads/release'
|
||||||
run: |
|
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
|
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
|
# Build master Docker image and push to Docker Hub
|
||||||
- name: Push master image to Docker Hub with commit tag
|
- name: Push master image to Docker Hub with commit tag
|
||||||
if: success() && github.ref == 'refs/heads/master'
|
if: success() && github.ref == 'refs/heads/master'
|
||||||
run: |
|
run: |
|
||||||
docker build -t appsmith/test-appsmith-repo:${GITHUB_SHA} .
|
docker build -t appsmith/appsmith-server:${GITHUB_SHA} .
|
||||||
docker build -t appsmith/test-appsmith-repo:latest .
|
docker build -t appsmith/appsmith-server:latest .
|
||||||
echo ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin
|
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
|
||||||
|
|
|
||||||
1
app/server/.gitignore
vendored
1
app/server/.gitignore
vendored
|
|
@ -12,3 +12,4 @@ node_modules
|
||||||
**/.classpath
|
**/.classpath
|
||||||
**/.project
|
**/.project
|
||||||
**/.factorypath
|
**/.factorypath
|
||||||
|
*.env
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,12 @@ import org.bson.internal.Base64;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.pf4j.Extension;
|
import org.pf4j.Extension;
|
||||||
import org.pf4j.PluginWrapper;
|
import org.pf4j.PluginWrapper;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.reactive.function.BodyInserters;
|
import org.springframework.web.reactive.function.BodyInserters;
|
||||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
@ -40,8 +42,7 @@ import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class RapidApiPlugin extends BasePlugin {
|
public class RapidApiPlugin extends BasePlugin {
|
||||||
private static final int MAX_REDIRECTS = 5;
|
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";
|
private static final String JSON_TYPE = "apipayload";
|
||||||
|
|
||||||
public RapidApiPlugin(PluginWrapper wrapper) {
|
public RapidApiPlugin(PluginWrapper wrapper) {
|
||||||
|
|
@ -52,11 +53,21 @@ public class RapidApiPlugin extends BasePlugin {
|
||||||
@Extension
|
@Extension
|
||||||
public static class RapidApiPluginExecutor implements PluginExecutor {
|
public static class RapidApiPluginExecutor implements PluginExecutor {
|
||||||
|
|
||||||
|
@Value("${rapidapi.key.name}")
|
||||||
|
private String rapidApiKeyName;
|
||||||
|
|
||||||
|
@Value("${rapidapi.key.value}")
|
||||||
|
private String rapidApiKeyValue;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Object> execute(Object connection,
|
public Mono<Object> execute(Object connection,
|
||||||
DatasourceConfiguration datasourceConfiguration,
|
DatasourceConfiguration datasourceConfiguration,
|
||||||
ActionConfiguration actionConfiguration) {
|
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 requestBody = (actionConfiguration.getBody() == null) ? "" : actionConfiguration.getBody();
|
||||||
String path = (actionConfiguration.getPath() == null) ? "" : actionConfiguration.getPath();
|
String path = (actionConfiguration.getPath() == null) ? "" : actionConfiguration.getPath();
|
||||||
String url = datasourceConfiguration.getUrl() + path;
|
String url = datasourceConfiguration.getUrl() + path;
|
||||||
|
|
@ -77,7 +88,7 @@ public class RapidApiPlugin extends BasePlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the rapid api headers
|
// 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 route parameters exist, update the URL by replacing the key surrounded by '{' and '}'
|
||||||
if (actionConfiguration.getRouteParameters() != null && !actionConfiguration.getRouteParameters().isEmpty()) {
|
if (actionConfiguration.getRouteParameters() != null && !actionConfiguration.getRouteParameters().isEmpty()) {
|
||||||
|
|
@ -258,7 +269,9 @@ public class RapidApiPlugin extends BasePlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<DatasourceTestResult> testDatasource(DatasourceConfiguration datasourceConfiguration) {
|
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) {
|
private void addHeadersToRequest(WebClient.Builder webClientBuilder, List<Property> headers) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,6 +2,8 @@ package com.appsmith.server.authentication.handlers;
|
||||||
|
|
||||||
import com.appsmith.server.configurations.CommonConfig;
|
import com.appsmith.server.configurations.CommonConfig;
|
||||||
import com.appsmith.server.constants.Security;
|
import com.appsmith.server.constants.Security;
|
||||||
|
import com.appsmith.server.exceptions.AppsmithError;
|
||||||
|
import com.appsmith.server.exceptions.AppsmithException;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
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 final StringKeyGenerator secureKeyGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96);
|
||||||
|
|
||||||
|
private static final String MISSING_VALUE_SENTINEL = "missing_value_sentinel";
|
||||||
|
|
||||||
private final CommonConfig commonConfig;
|
private final CommonConfig commonConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -111,7 +115,13 @@ public class CustomServerOAuth2AuthorizationRequestResolver implements ServerOAu
|
||||||
public Mono<OAuth2AuthorizationRequest> resolve(ServerWebExchange exchange,
|
public Mono<OAuth2AuthorizationRequest> resolve(ServerWebExchange exchange,
|
||||||
String clientRegistrationId) {
|
String clientRegistrationId) {
|
||||||
return this.findByRegistrationId(exchange, 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) {
|
private Mono<ClientRegistration> findByRegistrationId(ServerWebExchange exchange, String clientRegistration) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -8,27 +8,27 @@ import lombok.Setter;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import reactor.core.scheduler.Scheduler;
|
import reactor.core.scheduler.Scheduler;
|
||||||
import reactor.core.scheduler.Schedulers;
|
import reactor.core.scheduler.Schedulers;
|
||||||
|
|
||||||
import javax.validation.Validation;
|
import javax.validation.Validation;
|
||||||
import javax.validation.Validator;
|
import javax.validation.Validator;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@Configuration
|
@Configuration
|
||||||
public class CommonConfig {
|
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;
|
private String allowedDomainList;
|
||||||
|
|
||||||
List<String> domainList;
|
private List<String> domainList;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Scheduler scheduler() {
|
public Scheduler scheduler() {
|
||||||
|
|
@ -49,17 +49,12 @@ public class CommonConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getAllowedDomains() {
|
public List<String> getAllowedDomains() {
|
||||||
if (allowedDomainList == null || allowedDomainList.trim().isEmpty()) {
|
if (domainList == null) {
|
||||||
return new ArrayList<>();
|
domainList = StringUtils.hasText(allowedDomainList)
|
||||||
|
? Arrays.asList(allowedDomainList.trim().split("\\s*,[,\\s]*"))
|
||||||
|
: Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.domainList == null) {
|
return domainList;
|
||||||
this.domainList = Arrays.asList(allowedDomainList.split(","))
|
|
||||||
.stream()
|
|
||||||
.filter(domain -> (domain != null && !domain.trim().isEmpty()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.domainList;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,5 @@ import org.springframework.context.annotation.Configuration;
|
||||||
@Getter
|
@Getter
|
||||||
public class MarketplaceConfig {
|
public class MarketplaceConfig {
|
||||||
@Value("${marketplace.base-url}")
|
@Value("${marketplace.base-url}")
|
||||||
String base_url;
|
String baseUrl;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
package com.appsmith.server.configurations;
|
package com.appsmith.server.configurations;
|
||||||
|
|
||||||
import com.rollbar.notifier.Rollbar;
|
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.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
|
@ -10,24 +11,35 @@ import org.springframework.core.env.Environment;
|
||||||
import static com.rollbar.notifier.config.ConfigBuilder.withAccessToken;
|
import static com.rollbar.notifier.config.ConfigBuilder.withAccessToken;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@ConditionalOnExpression(value="!'${com.rollbar.access-token:}'.isEmpty()")
|
||||||
public class RollbarConfig {
|
public class RollbarConfig {
|
||||||
|
|
||||||
@Value("${com.rollbar.access-token}")
|
@Value("${com.rollbar.access-token}")
|
||||||
String rollbarAccessToken;
|
private String rollbarAccessToken;
|
||||||
|
|
||||||
// Allow being able to disable Rollbar in dev/test environments.
|
@Value("${rollbar.env:}")
|
||||||
// If the `rollbar.enabled` property is not set, it defaults to `true` (by the `:true` part below).
|
private String rollbarEnv;
|
||||||
@Value("#{new Boolean('${rollbar.enabled:true}'.trim())}")
|
|
||||||
boolean rollbarEnabled;
|
|
||||||
|
|
||||||
@Autowired
|
final Environment env;
|
||||||
Environment env;
|
|
||||||
|
public RollbarConfig(Environment env) {
|
||||||
|
this.env = env;
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
Rollbar rollbarConfiguration() {
|
Rollbar rollbarConfiguration() {
|
||||||
return Rollbar.init(withAccessToken(rollbarAccessToken)
|
// The Rollbar env, if not set, defaults to being the first Spring profile.
|
||||||
.enabled(rollbarEnabled)
|
String environment = rollbarEnv;
|
||||||
.environment(env.getActiveProfiles()[0])
|
if ((environment == null || environment.isEmpty()) && env.getActiveProfiles().length > 0) {
|
||||||
.build());
|
environment = env.getActiveProfiles()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigBuilder builder = withAccessToken(rollbarAccessToken);
|
||||||
|
|
||||||
|
if (environment != null) {
|
||||||
|
builder = builder.environment(environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Rollbar.init(builder.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,14 @@ package com.appsmith.server.configurations;
|
||||||
|
|
||||||
import com.segment.analytics.Analytics;
|
import com.segment.analytics.Analytics;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
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.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@ConditionalOnExpression(value="!'${segment.writeKey:}'.isEmpty()")
|
||||||
public class SegmentConfig {
|
public class SegmentConfig {
|
||||||
|
|
||||||
@Value("${segment.writeKey}")
|
@Value("${segment.writeKey}")
|
||||||
private String writeKey;
|
private String writeKey;
|
||||||
|
|
||||||
|
|
@ -14,4 +17,5 @@ public class SegmentConfig {
|
||||||
public Analytics analyticsRunner() {
|
public Analytics analyticsRunner() {
|
||||||
return Analytics.builder(writeKey).build();
|
return Analytics.builder(writeKey).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@ public enum AppsmithError {
|
||||||
DATASOURCE_HAS_ACTIONS(409, 4030, "Cannot delete datasource since it has {0} action(s) using it."),
|
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."),
|
ORGANIZATION_ID_NOT_GIVEN(400, 4031, "Missing organization id. Please enter one."),
|
||||||
INVALID_CURL_METHOD(400, 4032, "Invalid method in cURL command: {0}."),
|
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."),
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package com.appsmith.server.exceptions;
|
||||||
import com.appsmith.external.pluginExceptions.AppsmithPluginException;
|
import com.appsmith.external.pluginExceptions.AppsmithPluginException;
|
||||||
import com.appsmith.server.dtos.ResponseDTO;
|
import com.appsmith.server.dtos.ResponseDTO;
|
||||||
import com.rollbar.notifier.Rollbar;
|
import com.rollbar.notifier.Rollbar;
|
||||||
import com.segment.analytics.Analytics;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
@ -23,15 +22,21 @@ import reactor.core.publisher.Mono;
|
||||||
@ControllerAdvice
|
@ControllerAdvice
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class GlobalExceptionHandler {
|
public class GlobalExceptionHandler {
|
||||||
private final Analytics analytics;
|
|
||||||
private final Rollbar rollbar;
|
private final Rollbar rollbar;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public GlobalExceptionHandler(Analytics analytics, Rollbar rollbar) {
|
public GlobalExceptionHandler(@Autowired(required = false) Rollbar rollbar) {
|
||||||
this.analytics = analytics;
|
|
||||||
this.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
|
* 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
|
* Ideally, we should only be throwing AppsmithException from our code. This ensures that we can standardize
|
||||||
|
|
@ -45,8 +50,7 @@ public class GlobalExceptionHandler {
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Mono<ResponseDTO<ErrorDTO>> catchAppsmithException(AppsmithException e, ServerWebExchange exchange) {
|
public Mono<ResponseDTO<ErrorDTO>> catchAppsmithException(AppsmithException e, ServerWebExchange exchange) {
|
||||||
exchange.getResponse().setStatusCode(HttpStatus.resolve(e.getHttpStatus()));
|
exchange.getResponse().setStatusCode(HttpStatus.resolve(e.getHttpStatus()));
|
||||||
log.error("", e);
|
doLog(e);
|
||||||
rollbar.log(e);
|
|
||||||
return Mono.just(new ResponseDTO<>(e.getHttpStatus(), new ErrorDTO(e.getAppErrorCode(), e.getMessage())));
|
return Mono.just(new ResponseDTO<>(e.getHttpStatus(), new ErrorDTO(e.getAppErrorCode(), e.getMessage())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,8 +59,7 @@ public class GlobalExceptionHandler {
|
||||||
public Mono<ResponseDTO<ErrorDTO>> catchDuplicateKeyException(org.springframework.dao.DuplicateKeyException e, ServerWebExchange exchange) {
|
public Mono<ResponseDTO<ErrorDTO>> catchDuplicateKeyException(org.springframework.dao.DuplicateKeyException e, ServerWebExchange exchange) {
|
||||||
AppsmithError appsmithError = AppsmithError.DUPLICATE_KEY;
|
AppsmithError appsmithError = AppsmithError.DUPLICATE_KEY;
|
||||||
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
|
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
|
||||||
log.error("", e);
|
doLog(e);
|
||||||
rollbar.log(e);
|
|
||||||
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
|
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
|
||||||
appsmithError.getMessage(e.getMessage()))));
|
appsmithError.getMessage(e.getMessage()))));
|
||||||
}
|
}
|
||||||
|
|
@ -66,8 +69,7 @@ public class GlobalExceptionHandler {
|
||||||
public Mono<ResponseDTO<ErrorDTO>> catchTimeoutException(java.util.concurrent.TimeoutException e, ServerWebExchange exchange) {
|
public Mono<ResponseDTO<ErrorDTO>> catchTimeoutException(java.util.concurrent.TimeoutException e, ServerWebExchange exchange) {
|
||||||
AppsmithError appsmithError = AppsmithError.PLUGIN_EXECUTION_TIMEOUT;
|
AppsmithError appsmithError = AppsmithError.PLUGIN_EXECUTION_TIMEOUT;
|
||||||
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
|
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
|
||||||
log.error("", e);
|
doLog(e);
|
||||||
rollbar.log(e);
|
|
||||||
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
|
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
|
||||||
appsmithError.getMessage())));
|
appsmithError.getMessage())));
|
||||||
}
|
}
|
||||||
|
|
@ -77,8 +79,7 @@ public class GlobalExceptionHandler {
|
||||||
public Mono<ResponseDTO<ErrorDTO>> catchServerWebInputException(ServerWebInputException e, ServerWebExchange exchange) {
|
public Mono<ResponseDTO<ErrorDTO>> catchServerWebInputException(ServerWebInputException e, ServerWebExchange exchange) {
|
||||||
AppsmithError appsmithError = AppsmithError.GENERIC_BAD_REQUEST;
|
AppsmithError appsmithError = AppsmithError.GENERIC_BAD_REQUEST;
|
||||||
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
|
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
|
||||||
log.error("", e);
|
doLog(e);
|
||||||
rollbar.log(e);
|
|
||||||
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
|
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
|
||||||
appsmithError.getMessage(e.getReason()))));
|
appsmithError.getMessage(e.getReason()))));
|
||||||
}
|
}
|
||||||
|
|
@ -88,8 +89,7 @@ public class GlobalExceptionHandler {
|
||||||
public Mono<ResponseDTO<ErrorDTO>> catchPluginException(AppsmithPluginException e, ServerWebExchange exchange) {
|
public Mono<ResponseDTO<ErrorDTO>> catchPluginException(AppsmithPluginException e, ServerWebExchange exchange) {
|
||||||
AppsmithError appsmithError = AppsmithError.INTERNAL_SERVER_ERROR;
|
AppsmithError appsmithError = AppsmithError.INTERNAL_SERVER_ERROR;
|
||||||
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
|
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
|
||||||
log.error("", e);
|
doLog(e);
|
||||||
rollbar.log(e);
|
|
||||||
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
|
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
|
||||||
e.getLocalizedMessage())));
|
e.getLocalizedMessage())));
|
||||||
}
|
}
|
||||||
|
|
@ -99,8 +99,7 @@ public class GlobalExceptionHandler {
|
||||||
public Mono<ResponseDTO<ErrorDTO>> catchAccessDeniedException(AccessDeniedException e, ServerWebExchange exchange) {
|
public Mono<ResponseDTO<ErrorDTO>> catchAccessDeniedException(AccessDeniedException e, ServerWebExchange exchange) {
|
||||||
AppsmithError appsmithError = AppsmithError.UNAUTHORIZED_ACCESS;
|
AppsmithError appsmithError = AppsmithError.UNAUTHORIZED_ACCESS;
|
||||||
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
|
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
|
||||||
log.error("", e);
|
doLog(e);
|
||||||
rollbar.log(e);
|
|
||||||
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
|
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
|
||||||
appsmithError.getMessage())));
|
appsmithError.getMessage())));
|
||||||
}
|
}
|
||||||
|
|
@ -118,8 +117,7 @@ public class GlobalExceptionHandler {
|
||||||
public Mono<ResponseDTO<ErrorDTO>> catchException(Exception e, ServerWebExchange exchange) {
|
public Mono<ResponseDTO<ErrorDTO>> catchException(Exception e, ServerWebExchange exchange) {
|
||||||
AppsmithError appsmithError = AppsmithError.INTERNAL_SERVER_ERROR;
|
AppsmithError appsmithError = AppsmithError.INTERNAL_SERVER_ERROR;
|
||||||
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
|
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
|
||||||
log.error("", e);
|
doLog(e);
|
||||||
rollbar.log(e);
|
|
||||||
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
|
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
|
||||||
appsmithError.getMessage())));
|
appsmithError.getMessage())));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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());
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -21,12 +21,16 @@ public class AnalyticsService<T extends BaseDomain> {
|
||||||
private final SessionUserService sessionUserService;
|
private final SessionUserService sessionUserService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public AnalyticsService(Analytics analytics, SessionUserService sessionUserService) {
|
public AnalyticsService(@Autowired(required = false) Analytics analytics, SessionUserService sessionUserService) {
|
||||||
this.analytics = analytics;
|
this.analytics = analytics;
|
||||||
this.sessionUserService = sessionUserService;
|
this.sessionUserService = sessionUserService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mono<User> trackNewUser(User user) {
|
public Mono<User> trackNewUser(User user) {
|
||||||
|
if (analytics == null) {
|
||||||
|
return Mono.just(user);
|
||||||
|
}
|
||||||
|
|
||||||
return Mono.just(user)
|
return Mono.just(user)
|
||||||
.map(savedUser -> {
|
.map(savedUser -> {
|
||||||
Map<String, String> traitsMap = new HashMap<>();
|
Map<String, String> traitsMap = new HashMap<>();
|
||||||
|
|
@ -44,6 +48,10 @@ public class AnalyticsService<T extends BaseDomain> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mono<T> sendEvent(String eventTag, T object) {
|
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
|
// 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
|
// Without this, a lot of flows meant for anonymous users will error out
|
||||||
Mono<User> userMono = sessionUserService.getCurrentUser();
|
Mono<User> userMono = sessionUserService.getCurrentUser();
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
@ -54,7 +55,7 @@ public class MarketplaceServiceImpl implements MarketplaceService {
|
||||||
this.marketplaceConfig = marketplaceConfig;
|
this.marketplaceConfig = marketplaceConfig;
|
||||||
this.webClient = webClientBuilder
|
this.webClient = webClientBuilder
|
||||||
.defaultHeaders(header -> header.setBasicAuth(MARKETPLACE_USERNAME, MARKETPLACE_PASSWORD))
|
.defaultHeaders(header -> header.setBasicAuth(MARKETPLACE_USERNAME, MARKETPLACE_PASSWORD))
|
||||||
.baseUrl(marketplaceConfig.getBase_url())
|
.baseUrl(marketplaceConfig.getBaseUrl())
|
||||||
.build();
|
.build();
|
||||||
this.objectMapper = objectMapper;
|
this.objectMapper = objectMapper;
|
||||||
}
|
}
|
||||||
|
|
@ -63,6 +64,10 @@ public class MarketplaceServiceImpl implements MarketplaceService {
|
||||||
public Mono<ProviderPaginatedDTO> getProviders(MultiValueMap<String, String> params) {
|
public Mono<ProviderPaginatedDTO> getProviders(MultiValueMap<String, String> params) {
|
||||||
URI uri = buildFullURI(params, PROVIDER_PATH);
|
URI uri = buildFullURI(params, PROVIDER_PATH);
|
||||||
|
|
||||||
|
if (uri == null) {
|
||||||
|
return Mono.error(new AppsmithException(AppsmithError.MARKETPLACE_NOT_CONFIGURED));
|
||||||
|
}
|
||||||
|
|
||||||
return webClient
|
return webClient
|
||||||
.get()
|
.get()
|
||||||
.uri(uri)
|
.uri(uri)
|
||||||
|
|
@ -85,6 +90,10 @@ public class MarketplaceServiceImpl implements MarketplaceService {
|
||||||
public Mono<List<ApiTemplate>> getTemplates(MultiValueMap<String, String> params) {
|
public Mono<List<ApiTemplate>> getTemplates(MultiValueMap<String, String> params) {
|
||||||
URI uri = buildFullURI(params, TEMPLATE_PATH);
|
URI uri = buildFullURI(params, TEMPLATE_PATH);
|
||||||
|
|
||||||
|
if (uri == null) {
|
||||||
|
return Mono.error(new AppsmithException(AppsmithError.MARKETPLACE_NOT_CONFIGURED));
|
||||||
|
}
|
||||||
|
|
||||||
return webClient
|
return webClient
|
||||||
.get()
|
.get()
|
||||||
.uri(uri)
|
.uri(uri)
|
||||||
|
|
@ -107,6 +116,10 @@ public class MarketplaceServiceImpl implements MarketplaceService {
|
||||||
public Mono<List<String>> getCategories() {
|
public Mono<List<String>> getCategories() {
|
||||||
URI uri = buildFullURI(null, CATEGORIES_PATH);
|
URI uri = buildFullURI(null, CATEGORIES_PATH);
|
||||||
|
|
||||||
|
if (uri == null) {
|
||||||
|
return Mono.error(new AppsmithException(AppsmithError.MARKETPLACE_NOT_CONFIGURED));
|
||||||
|
}
|
||||||
|
|
||||||
return webClient
|
return webClient
|
||||||
.get()
|
.get()
|
||||||
.uri(uri)
|
.uri(uri)
|
||||||
|
|
@ -132,8 +145,7 @@ public class MarketplaceServiceImpl implements MarketplaceService {
|
||||||
URI uri = buildFullURI(params, USE_PROVIDER_API);
|
URI uri = buildFullURI(params, USE_PROVIDER_API);
|
||||||
|
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
// Throw an internal server error because the URL is hard coded and must be correct
|
return Mono.error(new AppsmithException(AppsmithError.MARKETPLACE_NOT_CONFIGURED));
|
||||||
return Mono.error(new AppsmithException(AppsmithError.INTERNAL_SERVER_ERROR));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return webClient
|
return webClient
|
||||||
|
|
@ -147,6 +159,10 @@ public class MarketplaceServiceImpl implements MarketplaceService {
|
||||||
public Mono<Provider> getProviderById(String id) {
|
public Mono<Provider> getProviderById(String id) {
|
||||||
URI uri = buildFullURI(null, PROVIDER_PATH + "/" + id);
|
URI uri = buildFullURI(null, PROVIDER_PATH + "/" + id);
|
||||||
|
|
||||||
|
if (uri == null) {
|
||||||
|
return Mono.error(new AppsmithException(AppsmithError.MARKETPLACE_NOT_CONFIGURED));
|
||||||
|
}
|
||||||
|
|
||||||
return webClient
|
return webClient
|
||||||
.get()
|
.get()
|
||||||
.uri(uri)
|
.uri(uri)
|
||||||
|
|
@ -174,6 +190,10 @@ public class MarketplaceServiceImpl implements MarketplaceService {
|
||||||
public Mono<List<Provider>> searchProviderByName(String name) {
|
public Mono<List<Provider>> searchProviderByName(String name) {
|
||||||
URI uri = buildFullURI(null, PROVIDER_PATH + "/name/" + URLEncoder.encode(name, StandardCharsets.UTF_8));
|
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
|
return webClient
|
||||||
.get()
|
.get()
|
||||||
.uri(uri)
|
.uri(uri)
|
||||||
|
|
@ -193,9 +213,14 @@ public class MarketplaceServiceImpl implements MarketplaceService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private URI buildFullURI(MultiValueMap<String, String> params, String path) {
|
private URI buildFullURI(MultiValueMap<String, String> params, String path) {
|
||||||
|
final String baseUrl = marketplaceConfig.getBaseUrl();
|
||||||
|
if (!StringUtils.hasText(baseUrl)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
UriComponentsBuilder uriBuilder = UriComponentsBuilder.newInstance();
|
UriComponentsBuilder uriBuilder = UriComponentsBuilder.newInstance();
|
||||||
try {
|
try {
|
||||||
uriBuilder.uri(new URI(marketplaceConfig.getBase_url() + path));
|
uriBuilder.uri(new URI(baseUrl + path));
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
log.error(e.getMessage());
|
log.error(e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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.
|
# 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
|
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:}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
dsn=https://5c388a93407a45a5886a941842e28d29@sentry.io/1758051
|
|
||||||
release=0.0.1
|
|
||||||
environment=local
|
|
||||||
stacktrace.hidecommon=false
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -3,8 +3,10 @@ version: "3.7"
|
||||||
services:
|
services:
|
||||||
appsmith-internal-server:
|
appsmith-internal-server:
|
||||||
image: arpitappsmith/appsmith-server:maven
|
image: arpitappsmith/appsmith-server:maven
|
||||||
|
env_file: envs/docker.env
|
||||||
environment:
|
environment:
|
||||||
- SPRING_PROFILES_ACTIVE=docker
|
APPSMITH_MONGODB_URI: "mongodb://mongo:27017/mobtools"
|
||||||
|
APPSMITH_REDIS_URL: "redis://redis:6379"
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
links:
|
links:
|
||||||
|
|
|
||||||
5
app/server/envs/dev.env.example
Normal file
5
app/server/envs/dev.env.example
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
APPSMITH_MONGODB_URI="mongodb://localhost:27017/mobtools"
|
||||||
|
|
||||||
|
APPSMITH_REDIS_URL="redis://127.0.0.1:6379"
|
||||||
16
app/server/envs/docker.env.example
Normal file
16
app/server/envs/docker.env.example
Normal 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
|
||||||
13
app/server/scripts/start-dev-server.sh
Executable file
13
app/server/scripts/start-dev-server.sh
Executable 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
|
||||||
Loading…
Reference in New Issue
Block a user